Skip to content

Commit

Permalink
Clean up the rest of the tests
Browse files Browse the repository at this point in the history
Now the only failing ones are scope/closure related. Which is going to
need some serious overhaul to fix. Not sure if I'll ever do it :p
  • Loading branch information
rctcwyvrn committed Aug 28, 2020
1 parent f68f971 commit 328b6c5
Show file tree
Hide file tree
Showing 21 changed files with 105 additions and 231 deletions.
160 changes: 4 additions & 156 deletions failing_tests.txt
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
=== all ===

FAIL test/assignment/infix_operator.lox
FAIL test/assignment/grouping.lox
Unexpected error:
[3] Error at '"value"': Expected ';' after value
Missing expected error: [3] Error at '=': Invalid assignment target


FAIL test/assignment/prefix_operator.lox
Unexpected error:
[2] Error at '"value"': Expected ';' after value
[2] Error at '=': Expected ';' after value
Missing expected error: [2] Error at '=': Invalid assignment target


FAIL test/assignment/to_this.lox
Unexpected error:
[3] Error at '"value"': Expected ';' after value
Missing expected error: [3] Error at '=': Invalid assignment target


FAIL test/class/local_reference_self.lox
Unexpected output on stderr:
Undefined variable 'Foo'
Expand Down Expand Up @@ -140,26 +128,6 @@ FAIL test/closure/unused_later_closure.lox
Missing expected output 'a' on line 27.


FAIL test/constructor/missing_arguments.lox
Expected runtime error 'Expected 2 arguments but got 1' and got:
Expected 2 arguments but got 1 instead


FAIL test/field/get_on_function.lox
Expected runtime error 'Only class instances can access properties with '.' Found <fn> instead' and got:
Only class instances can access properties with '.' Found <pointer 0> to <fn foo | ObjClosure { function: 1, values: [] }> instead


FAIL test/field/set_on_function.lox
Expected runtime error 'Only class instances can access properties with '.' Found <fn> instead' and got:
Only class instances can access properties with '.' Found <pointer 0> to <fn foo | ObjClosure { function: 1, values: [] }> instead


FAIL test/field/undefined.lox
Expected runtime error 'Undefined property 'bar'' and got:
Undefined property 'bar' in ObjInstance { class: 0, fields: {} }


FAIL test/for/closure_in_body.lox
Unexpected output on stderr:
Undefined variable 'i'
Expand Down Expand Up @@ -193,14 +161,6 @@ FAIL test/for/scope.lox
Missing expected output '0' on line 24.


FAIL test/for/statement_condition.lox
Missing expected error: [3] Error at ')': Expected ';' after expression


FAIL test/for/statement_initializer.lox
Missing expected error: [3] Error at ')': Expected ';' after expression


FAIL test/function/local_recursion.lox
Unexpected output on stderr:
Undefined variable 'fib'
Expand All @@ -215,124 +175,12 @@ FAIL test/function/local_recursion.lox
Missing expected output '21' on line 7.


FAIL test/function/print.lox
Expected output '<native fn>' on line 4 and got '<native_fn>'.


FAIL test/function/too_many_parameters.lox
Unexpected error:
[257] Error at ',': Cannot have more than 255 parameters
Missing expected error: [257] Error at 'a': Cannot have more than 255 parameters


FAIL test/limit/loop_too_large.lox
Missing expected error: [2351] Error at '}': Loop body too large
Expected return code 65 and got 0. Stderr:


FAIL test/limit/no_reuse_constants.lox
Missing expected error: [35] Error at '1': Too many constants in one chunk
Expected return code 65 and got 0. Stderr:


FAIL test/limit/too_many_constants.lox
Missing expected error: [35] Error at '"oops"': Too many constants in one chunk
Expected return code 65 and got 0. Stderr:


FAIL test/limit/too_many_locals.lox
Missing expected error: [52] Error at 'oops': Too many local variables in function
Expected return code 65 and got 0. Stderr:


FAIL test/limit/too_many_upvalues.lox
Missing expected error: [102] Error at 'oops': Too many closure variables in function
Expected return code 65 and got 0. Stderr:


FAIL test/method/too_many_parameters.lox
Unexpected error:
[258] Error at ',': Cannot have more than 255 parameters
Missing expected error: [258] Error at 'a': Cannot have more than 255 parameters


FAIL test/number/decimal_point_at_eof.lox
Unexpected error:
[2] Error at end of file: Expected property name after '.'
Missing expected error: [2] Error at end: Expected property name after '.'


FAIL test/operator/equals_class.lox
Expected output 'true' on line 5 and got 'false'.
Expected output 'true' on line 8 and got 'false'.
Expected output 'false' on line 11 and got 'true'.


FAIL test/operator/equals_method.lox
Expected output 'true' on line 10 and got 'false'.


FAIL test/regression/40.lox
Expected output 'false' on line 4 and got 'true'.


FAIL test/string/unterminated.lox
Unexpected output on stderr:
[Line 2] Error: Expected expression
[Line 2] Error: Unterminated string
Missing expected error: [2] Error: Unterminated string


FAIL test/super/extra_arguments.lox
Expected runtime error 'Expected 2 arguments but got 4' and got:
Expected 2 arguments but got 4 instead


FAIL test/super/missing_arguments.lox
Expected runtime error 'Expected 2 arguments but got 1' and got:
Expected 2 arguments but got 1 instead


FAIL test/super/no_superclass_method.lox
Expected runtime error 'Undefined property 'doesNotExist'' and got:
Undefined superclass method 'doesNotExist' for ObjInstance { class: 1, fields: {} }


FAIL test/super/super_in_closure_in_inherited_method.lox
Expected output 'A' on line 26 and got 'B'.


FAIL test/super/super_in_inherited_method.lox
Expected output 'A' on line 23 and got 'B'.


FAIL test/super/super_without_dot.lox
Unexpected error:
[9] Error at end of file: Expected '}' after block


FAIL test/super/super_without_name.lox
Unexpected error:
[8] Error at end of file: Expected '}' after block


FAIL test/this/nested_class.lox
Expected output 'Outer instance' on line 3 and got '<pointer 0> to <instance 0>'.
Expected output 'Outer instance' on line 6 and got '<pointer 0> to <instance 0>'.
Expected output 'Inner instance' on line 10 and got '<pointer 2> to <instance 1>'.


FAIL test/this/this_at_top_level.lox
Unexpected error:
[1] Error at 'this': Cannot use keyword 'this' outside of a class
Missing expected error: [1] Error at 'this': Cannot use 'this' outside of a class


FAIL test/this/this_in_top_level_function.lox
Unexpected error:
[2] Error at 'this': Cannot use keyword 'this' outside of a class
Missing expected error: [2] Error at 'this': Cannot use 'this' outside of a class


FAIL test/variable/shadow_and_local.lox
Expected output 'inner' on line 6 and got 'outer'.

Expand All @@ -357,4 +205,4 @@ FAIL test/while/closure_in_body.lox
Missing expected output '3' on line 19.


198 tests passed. 47 tests failed.
224 tests passed. 17 tests failed.
26 changes: 22 additions & 4 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,20 +598,33 @@ impl Compiler<'_> {
fn super_(&mut self) {
if self.current_class == None {
self.error("Cannot use keyword 'super' outside of a class");
} else if self.current_class().superclass == None {
self.error("Cannot use keyword 'super' in a class which does not inherit a class");
return; // Ideally we would attempt to compile the rest of the expression, but trying to continue will cause a panic
}

let superclass_index = if self.current_class().superclass == None {
self.error("Cannot use keyword 'super' in a class which does not inherit a class");
0 // Random value, we don't care that this value is wrong because we're going to exit because of the error anyway
} else {
self.current_class().superclass.unwrap()
};

self.consume(TokenType::TokenDot, "Expected '.' after 'super'");
self.consume(
TokenType::TokenIdentifier,
"Expected superclass method name",
);
let name = self.previous().lexemme.clone();
let name_index = self.identifier_constant(&name);
//self.emit_instr(OpCode::OpGetLocal(0)); // Fixme: Slightly sketchy hack to throw the LoxPointer into the right spot.

// At the time of OpGetSuper we want to know 2 things
// 1. The superclass we're going to be looking for values in
// 2. A pointer to the instance we want to bind the method to

let superclass_val = Value::LoxClass(superclass_index);
self.emit_constant(superclass_val);
self.named_variable(&String::from("this"), false); // Slightly better?
self.emit_instr(OpCode::OpGetSuper(name_index));

}

fn method(&mut self) {
Expand Down Expand Up @@ -979,7 +992,12 @@ impl Compiler<'_> {
if fn_chunk.fn_type != FunctionType::Method
&& fn_chunk.fn_type != FunctionType::Initializer
{
disassemble_fn_chunk(index, &fn_chunk, &self.constants, &self.identifier_constants);
disassemble_fn_chunk(
index,
&fn_chunk,
&self.constants,
&self.identifier_constants,
);
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ pub fn disassemble_class_chunk(
None => eprintln!("== <class {}> ===============", &class_chunk.name),
}
for (name, fn_index) in class_chunk.methods.iter() {
eprintln!("== <method {} | #{}> ============", identifiers.get(*name).unwrap(), fn_index);
eprintln!(
"== <method {} | #{}> ============",
identifiers.get(*name).unwrap(),
fn_index
);
disassemble_chunk(&function_defs[*fn_index].chunk, constants, identifiers);
}
}
Expand Down
13 changes: 10 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::process::exit;

fn main() {
let args: Vec<String> = env::args().collect();

if args.len() >= 2 {
let debug = (args.len() == 3) && args[2].eq("--debug");
let result = run_file(args.get(1).unwrap(), debug);
std::process::exit(match result {
exit(match result {
InterpretResult::InterpretOK => 0,
InterpretResult::InterpretCompileError => 65,
InterpretResult::InterpretRuntimeError => 70,
Expand All @@ -27,12 +28,18 @@ fn run_file(filename: &String, debug: bool) -> InterpretResult {

let mut file = match File::open(&path) {
Ok(file) => file,
Err(why) => panic!("Failed to open {}: {}", path_display, why),
Err(why) => {
eprintln!("Failed to open {}: {}", path_display, why);
exit(1);
}
};

let mut s = String::new();
match file.read_to_string(&mut s) {
Ok(_) => return rlox::interpret(&s, debug, false),
Err(why) => panic!("Failed to read {}: {}", path_display, why),
Err(why) => {
eprintln!("Failed to read {}: {}", path_display, why);
exit(1);
}
};
}
2 changes: 1 addition & 1 deletion src/scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl Scanner<'_> {
}

if self.is_at_end() {
return self.error_token(String::from("Missing delimiter for string"));
return self.error_token(String::from("Unterminated string"));
}

self.advance(); // Step over the closing quote
Expand Down
2 changes: 1 addition & 1 deletion src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl HeapObjVal {
.unwrap(),
closure
),
HeapObjVal::LoxInstance(instance) => format!("<instance {}>", instance.class),
HeapObjVal::LoxInstance(instance) => format!("<instance {}>", vm.classes.get(instance.class).unwrap().name),
HeapObjVal::HeapPlaceholder => {
panic!("VM panic! How did a placeholder value get here?")
}
Expand Down
69 changes: 34 additions & 35 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -644,44 +644,43 @@ impl VM {
// This is almost identical to OpGetProperty, but it goes one extra jump to get the method from the superclass, and binds it to itself
OpCode::OpGetSuper(name_index) => {
let pointer_val = state.peek();

// Todo: Combine this and SetProperty into a macro so it doesn't hurt me everytime i have to read this
match state.deref_into(pointer_val, HeapObjType::LoxInstance) {
Ok(instance) => {
let instance = instance.as_instance();
let class_chunk = &self.classes[instance.class];
if class_chunk.superclass == None {
self.runtime_error("Cannot use keyword 'super' in a class that does not have a superclass", &state);
// Note: I think the compiiler can catch this
let superclass_val = state.peek_at(1);
if let Value::LoxClass(superclass) = superclass_val {
// Todo: Combine this and SetProperty into a macro so it doesn't hurt me everytime i have to read this
match state.deref_into(pointer_val, HeapObjType::LoxInstance) {
Ok(instance) => {
let instance = instance.as_instance();
let superclass_chunk = &self.classes[*superclass];
if superclass_chunk.methods.contains_key(&name_index) {
let bound_value = ObjBoundMethod {
method: *superclass_chunk.methods.get(&name_index).unwrap(),
pointer: pointer_val.as_pointer(),
};
// println!("Superclass get method found method {:?} ", bound_value);
// println!("Superclass methods {:?}", superclass_chunk.methods);
// println!("Superclass for {:?} is {:?}", instance, class_chunk.superclass);
state.pop(); // Remove the instance
state.stack.push(Value::LoxBoundMethod(bound_value));
// Replace with bound method
} else {
self.runtime_error(
format!(
"Undefined superclass method '{}' for {}",
self.get_variable_name(name_index),
self.classes.get(instance.class).unwrap().name,
)
.as_str(),
&state,
);
return InterpretResult::InterpretRuntimeError;
}
}
let superclass_chunk = &self.classes[class_chunk.superclass.unwrap()];
if superclass_chunk.methods.contains_key(&name_index) {
let bound_value = ObjBoundMethod {
method: *superclass_chunk.methods.get(&name_index).unwrap(),
pointer: pointer_val.as_pointer(),
};
println!("Superclass get method found method {:?} ", bound_value);
println!("Superclass methods {:?}", superclass_chunk.methods);
println!("Superclass for {:?} is {:?}", instance, class_chunk.superclass);
state.pop(); // Remove the instance
state.stack.push(Value::LoxBoundMethod(bound_value));
// Replace with bound method
} else {
self.runtime_error(
format!(
"Undefined superclass method '{}' for {}",
self.get_variable_name(name_index),
self.classes.get(instance.class).unwrap().name,
)
.as_str(),
&state,
);
return InterpretResult::InterpretRuntimeError;
Err(_) => {
panic!("VM panic! Failed to obtain instance LoxPointer for super");
}
}
Err(_) => {
panic!("VM panic! Failed to obtain instance LoxPointer for super");
}
} else {
panic!("VM panic! Failed to obtain superclass index for super, got {:?} instead", superclass_val);
}
}

Expand Down
Loading

0 comments on commit 328b6c5

Please sign in to comment.