From 2a9d5c98c4d08f19dec67e2a782ece56091b3b35 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Sun, 7 Jun 2020 15:45:25 +0100 Subject: [PATCH] Add the 'fields' primitive. This returns a class's fields. However, SOM's semantics on this are currently unclear (see https://github.com/SOM-st/SOM/issues/40). Although we allow users to mutate the 'methods' array, this is less sensible with fields in my opinion, since it would turn SOM from a statically into a dynamically scoped language. Thus, each time you call 'fields' you get a fresh array back such that any mutations made are ignored (see the `mutate_fields` test). --- lang_tests/instance_fields.som | 19 +++++++++++++++++++ lang_tests/mutate_fields.som | 29 +++++++++++++++++++++++++++++ src/lib/vm/core.rs | 6 +++++- src/lib/vm/objects/class.rs | 11 ++++++++++- 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 lang_tests/instance_fields.som create mode 100644 lang_tests/mutate_fields.som diff --git a/lang_tests/instance_fields.som b/lang_tests/instance_fields.som new file mode 100644 index 00000000..c8ce65c0 --- /dev/null +++ b/lang_tests/instance_fields.som @@ -0,0 +1,19 @@ +" +VM: + status: success + stdout: + instance of Array + true + true +" + +instance_fields = ( + | x y | + run = ( + | fds | + fds := instance_fields fields. + fds println. + (fds contains: #x) println. + (fds contains: #y) println. + ) +) diff --git a/lang_tests/mutate_fields.som b/lang_tests/mutate_fields.som new file mode 100644 index 00000000..c9784f4e --- /dev/null +++ b/lang_tests/mutate_fields.som @@ -0,0 +1,29 @@ +" +VM: + status: success + stdout: + true + true + true + true + false +" + +mutate_fields = ( + | x y | + run = ( + | fds | + fds := mutate_fields fields. + (fds contains: #x) println. + (fds contains: #y) println. + fds at: 1 put: #z. + fds := mutate_fields fields. + (fds contains: #x) println. + (fds contains: #y) println. + (fds contains: #z) println. + ) + + find: sym = ( + method_holder methods do: [:e | ((e signature) == sym) ifTrue: [ ^e ]]. + ) +) diff --git a/src/lib/vm/core.rs b/src/lib/vm/core.rs index 57e9e463..06c61a24 100644 --- a/src/lib/vm/core.rs +++ b/src/lib/vm/core.rs @@ -717,7 +717,11 @@ impl VM { )) } } - Primitive::Fields => todo!(), + Primitive::Fields => { + let fields = stry!(rcv.downcast::(self)).fields(self); + self.stack.push(fields); + SendReturn::Val + } Primitive::FromString => todo!(), Primitive::FullGC => todo!(), Primitive::Global => { diff --git a/src/lib/vm/objects/class.rs b/src/lib/vm/objects/class.rs index 3bda8754..9e9baf16 100644 --- a/src/lib/vm/objects/class.rs +++ b/src/lib/vm/objects/class.rs @@ -12,7 +12,7 @@ use rboehm::Gc; use crate::vm::{ core::VM, error::{VMError, VMErrorKind}, - objects::{Array, Method, MethodsArray, Obj, ObjType, StaticObjType, String_}, + objects::{Array, Method, MethodsArray, NormalArray, Obj, ObjType, StaticObjType, String_}, val::{NotUnboxable, Val, ValKind}, }; @@ -164,6 +164,15 @@ impl Class { } } + pub fn fields(&self, vm: &mut VM) -> Val { + let field_strs = self + .inst_vars_map + .keys() + .map(|k| String_::new_sym(vm, k.clone())) + .collect(); + NormalArray::from_vec(vm, field_strs) + } + pub fn methods(&self, _: &VM) -> Val { self.methods }