Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Object Literals #86

Closed
smarr opened this issue Jan 12, 2017 · 4 comments
Closed

Add support for Object Literals #86

smarr opened this issue Jan 12, 2017 · 4 comments
Labels
enhancement Improves the implementation with something noteworthy good first issue Are you trying to have a good at SOMns? Start here! language-design Not everything is in the spec, sometimes, we need to decide what's best.

Comments

@smarr
Copy link
Owner

smarr commented Jan 12, 2017

Object Literals are defined in the Newspeak spec sec. 5.1.10.

Depending on the context where they are defined, they either have the current activation (i.e. Truffle frame) as context, or nil. From that I derive that object literals can only be defined either on the module level or within a method.

The proposed syntax is objectLiteral = (identifier, keywordMsg opt) opt, classBody.

This means, we could have the following code:

public foo = (
  | local obj val |
  local := 1.
  obj := ( | public field = local. |
               local println.
         )(
           public class Baz = ()()
           public println = ( field println. local := local + 1. )
         ).

  obj println. (* => 1 *)
  local println. (* => 2 *)

 val := Value ()() (* => Signals a NotAValue exception *)
)

For the implementation, beside the parser changes, there is at least one change needed:
SClass is defined with final SObjectWithClass enclosingObject to represent the outer scope. This needs to be changed so that the outer scope also can be a MaterializedFrame. This should be a straightforward change, there are only two things that depend on it: reading of the outer object which is either done with the outer keyword for an outer send, or for an implicit send. This does likely not need any adaptation, beside potential casts, because, access to local variables, i.e., the sends to the current activation are not done as 'sends' but are directly done as local variable accesses. I am not entirely clear on whether there are any issues in the parser's lookup logic for determining whether it is a variable read or a message send, though. Currently, it first checks for local variables, and then does a send. That might be more involved with the additional nesting logic.

The second thing that needs the enclosing object is the check whether a class is a value. That might be a bit more involved. Currently it should be simply returning false for activations, I presume. Except perhaps if they don't have locals. That gets more complicated if we actually start supporting lazy slots (promise slots, not sure what the spec term is) and immutable slots, but, we currently don't have that.

I am not sure what else interferes with it, there might be more.

@smarr smarr added enhancement Improves the implementation with something noteworthy language-design Not everything is in the spec, sometimes, we need to decide what's best. good first issue Are you trying to have a good at SOMns? Start here! labels Jan 12, 2017
@smarr
Copy link
Owner Author

smarr commented Jan 27, 2017

This task is likely going to be worked on by richard-roberts for Grace support.

@ghost
Copy link

ghost commented Feb 1, 2017

Thanks for the initial thoughts here @smarr. In the example you provide above, I am not clear on whether the println method is an instance method of obj (the outer object literal) or the inner nested class.

As per the following example, my interpretation is that println is to be an instance method belonging to the outer object literal (and that the inner nest class is declared simply to show that it is possible to nest classes in object literals). Is this correct?

  obj := 
    (* Object literal initializer *)
    (
      | 
        public field = local.
      | 
      local println.
    )

    (* Object literal body *)
    (
      (* A class nested into the object literal's body *)
      public class <superclass identifier>()()

      (* An instance method of the object literal *)
      public println = ( field println. local := local + 1. ).
    )

@smarr
Copy link
Owner Author

smarr commented Feb 1, 2017

I updated my initial example, reformated it, and added a missing closing parenthesis.
The idea was that println is a method of the object literal defined, which changes the count of local, which is visible is the subsequent println.
So, it was supposed to be as you showed in your example, indeed.
(I also gave the inner class a name and fixed its definition.)

@smarr
Copy link
Owner Author

smarr commented Aug 7, 2017

Implemented with #112.

@smarr smarr closed this as completed Aug 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improves the implementation with something noteworthy good first issue Are you trying to have a good at SOMns? Start here! language-design Not everything is in the spec, sometimes, we need to decide what's best.
Projects
None yet
Development

No branches or pull requests

1 participant