From 5e00d91257a8865f90f0836e65bbcddb237078a5 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Tue, 9 Jun 2020 17:29:48 +0100 Subject: [PATCH 1/2] Error when a user tries to redefine a field used in a superclass. --- lang_tests/instance_fields_overlap/test.som | 13 +++++++++++++ lang_tests/instance_fields_overlap/test_super.som | 3 +++ src/lib/compiler/ast_to_instrs.rs | 9 +++++++++ 3 files changed, 25 insertions(+) create mode 100644 lang_tests/instance_fields_overlap/test.som create mode 100644 lang_tests/instance_fields_overlap/test_super.som diff --git a/lang_tests/instance_fields_overlap/test.som b/lang_tests/instance_fields_overlap/test.som new file mode 100644 index 00000000..709135a7 --- /dev/null +++ b/lang_tests/instance_fields_overlap/test.som @@ -0,0 +1,13 @@ +" +VM: + status: error + stderr: + ...test.som', line 10, column 23: + test = test_super ( | a | + Field 'a' is already defined in a superclass. +" + +test = test_super ( | a | + run = ( + ) +) diff --git a/lang_tests/instance_fields_overlap/test_super.som b/lang_tests/instance_fields_overlap/test_super.som new file mode 100644 index 00000000..f5f95b34 --- /dev/null +++ b/lang_tests/instance_fields_overlap/test_super.som @@ -0,0 +1,3 @@ +test_super = ( + | a | +) diff --git a/src/lib/compiler/ast_to_instrs.rs b/src/lib/compiler/ast_to_instrs.rs index 8ce3200f..504bbece 100644 --- a/src/lib/compiler/ast_to_instrs.rs +++ b/src/lib/compiler/ast_to_instrs.rs @@ -153,6 +153,15 @@ impl<'a, 'input> Compiler<'a, 'input> { .iter() .map(|(k, v)| (k.to_owned(), *v)), ); + for var in ast_inst_vars { + let n = lexer.span_str(*var); + if inst_vars.contains_key(n) { + return Err(vec![( + *var, + format!("Field '{}' is already defined in a superclass.", n), + )]); + } + } inst_vars } else { HashMap::with_capacity(ast_inst_vars.len()) From 4d6ba76b2e534804b116f9eab9634a4847b5a561 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Tue, 9 Jun 2020 17:36:04 +0100 Subject: [PATCH 2/2] Don't allow the user to define the same field name in a class more than once. --- lang_tests/instance_fields_overlap2.som | 12 ++++++++++++ src/lib/compiler/ast_to_instrs.rs | 16 +++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 lang_tests/instance_fields_overlap2.som diff --git a/lang_tests/instance_fields_overlap2.som b/lang_tests/instance_fields_overlap2.som new file mode 100644 index 00000000..2a9419ee --- /dev/null +++ b/lang_tests/instance_fields_overlap2.som @@ -0,0 +1,12 @@ +" +VM: + status: error + stderr: + ...instance_fields_overlap2.som', line 11, column 9: + | a a | + Field 'a' has already been defined in this class. +" + +instance_field_overlap2 = ( + | a a | +) diff --git a/src/lib/compiler/ast_to_instrs.rs b/src/lib/compiler/ast_to_instrs.rs index 504bbece..be6929c2 100644 --- a/src/lib/compiler/ast_to_instrs.rs +++ b/src/lib/compiler/ast_to_instrs.rs @@ -168,7 +168,21 @@ impl<'a, 'input> Compiler<'a, 'input> { }; for var in ast_inst_vars { let vars_len = inst_vars.len(); - inst_vars.insert(lexer.span_str(*var).to_owned(), vars_len); + let n = lexer.span_str(*var).to_owned(); + match inst_vars.entry(n) { + hash_map::Entry::Occupied(_) => { + return Err(vec![( + *var, + format!( + "Field '{}' has already been defined in this class.", + self.lexer.span_str(*var) + ), + )]) + } + hash_map::Entry::Vacant(e) => { + e.insert(vars_len); + } + } } self.vars_stack.push(inst_vars);