-
Notifications
You must be signed in to change notification settings - Fork 30
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
Array literals implementation #173
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for updating the PR!
I got a number of things that still require some work. Some nitpicking about style consistency with the existing code, and some things that seem a bit problematic with the optimization.
Depending on your interest in this, do you want me to do these changes, or do you prefer to do them yourselves? Either way is fine for me :)
Thanks!
@@ -89,6 +89,7 @@ class TestRunner usingPlatform: platform = ( | |||
'DoubleTests', | |||
'IntegerTests', | |||
'StringTests', | |||
'ArrayLiteralTests', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should also be added in https://github.com/smarr/SOMns/blob/master/tests/java/som/tests/SomTests.java#L49
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
]. | ||
|
||
self assert: sum equals: 500500. | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the tests are using simple literals.
I think, we would also want tests where arrays contain complex expressions.
public class GenericArrayLiteralNode extends LiteralNode { | ||
@Children protected final ExpressionNode[] expressions; | ||
|
||
public GenericArrayLiteralNode(final List<ExpressionNode> expressions, final SourceSection source) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move the conversion to an array into the parser.
It is handled there normally, or in a SNodeFactory method perhaps.
} | ||
|
||
@ExplodeLoop | ||
protected SMutableArray evaluatedExpressions(final VirtualFrame frame) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name seems strange to me.
why 'evaluated'?
why 'expressions'?
Doesn't really match other nodes in SOMns.
Why not simply having this in executeGeneric()
?
arr[i] = expressions[i].executeGeneric(frame); | ||
} | ||
|
||
GenericArrayLiteralNode replacedNode = this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The remainder of this function is problematic.
The name of the node suggests it is the generic case, which means, it is the most general node, which is the final case of a set of specializations, usually the worst case.
So, you can't really do specializations here because it is confusing with respect to the rest of the system's conventions.
The node should probably be name UninitializedArrayLiteralNode
instead, and the logic of replacing the node is typically move into a specialize()
method.
|
||
GenericArrayLiteralNode replacedNode = this; | ||
|
||
if (allComponentsAreBoolean(arr)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I am not sure this is the best way of doing it. Did you see evaluateFirstDetermineStorageAndEvaluateRest(.)
? I would try to stick to existing approaches, and possibly even reuse the code.
Which might also mean that we don't need a separate class for each type of array literal.
try { | ||
arr[i] = expressions[i].executeBoolean(frame); | ||
} catch (UnexpectedResultException e) { | ||
throw new RuntimeException("Expression " + i + " of this BooleanArrayLiteralNode did not evaluate to a double"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ehm, ok?
That's not a semantically correct way to handle it :)
You can cheat, as long as you don't get caught :)
I've changed how the specialisation is done and now use a (simpler) specialise method instead of the separate classes. I considered reusing behaviour from evaluateFirstDetermineStorageAndEvaluateRest as @smarr suggested, but I would need to wrap the array literal's expressions into an |
@Richard-Roberts, I took the liberty to rebase the branch on Further, I changed the symbols to use the names from the Newspeak spec. I am also thinking of squashing some of the inbetween commits, if that's ok with you. |
@ExplodeLoop | ||
private boolean headSameTypeAsTail(final Object[] evaluated) { | ||
for (int i = 1; i < evaluated.length; i++) { | ||
if (!(evaluated[i].getClass().equals(evaluated[0].getClass()))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comparing the classes here does unfortunately not really work, since we have a wide range of classes floating around, not just primitives and objects.
@Richard-Roberts please have a look at my changes. Specializations need to form a minimal state machine, which reaches a stable point as fast as possible. Each state in the state machine is one specialization. The state transitions are defined by the 'guards'. With my implementation, we now got a state machine which looks like this:
Further, the implementation does ideally only allocate the array that is needed, so, I speculate on everything being the same type as the first element. You checked that somehow, but there was always an Object[] if I am not mistaken. And finally, I moved the implementation into Hope this makes somewhat sense. |
I adapted code to use array literals where it makes sense. |
One more todo item for this: the dynamic metric tool needs to be taught about array literals to count their allocation |
- these are not tuple literals as defined in the spec v0.1 sec. 5.1.7, instead they are mutable arrays - the parser uses symbol names from Newspeak spec, which is inconsistent with the other symbol names, but we slowly should migrate to the names from the spec
- simple tests and complex expressions - homogeneous and mixed types - test specializations, and storage transitions - added test file in runner and SomTests
- also make sure that specialization happens only once, if possible Signed-off-by: Stefan Marr <[email protected]>
Signed-off-by: Stefan Marr <[email protected]>
- also update dym test data Signed-off-by: Stefan Marr <[email protected]>
Ok, from my perspective, this would be done and ready to be merged. The final diff is identical to the current changes on your branch, but I simplified the history to focus on the essence of the changes. Will make our life easier to figure out issues in the future. If that all works for you, I'll merge things as soon as possible. |
@Override | ||
protected Object executeSpecialized(final VirtualFrame frame) { | ||
return ArraySetAllStrategy.evalForRemaining(frame, expressions, | ||
new Object[expressions.length], SArray.FIRST_IDX); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there ever a case where Array.FIRST_IDX
will not be zero?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's an artifact of my work on metaobject protocols, for those, I put some hidden things into arrays, then it wasn't 0. At the moment it is, but I kept it around for the possibility that I might need it one day. Not sure it's a great idea.
@smarr thanks for picking up the slack and pushing this PR along. I've looked over the changes and checked the benchmarks - let's merge this thing! |
This PR implements array literals, which means we can finally write down things like
{1. 4*8. Random new next } at: 3
as in other languages, and do away with much of theArray with: 1 with: 4*8
verboseness.A revamp of #100 to provide support array literals (see #83). With these changes, Newspeak's tuple literals are parsed as an
GenericArrayLiteralNode. The node is instantiated with the list of expressions declared in the tuple, each of which are evaluated and stored into a newObject[]
. If each of the expressions are evaluated to the same type, then theObject[]
is replaced with a more specialised array (long[]
,double[]
, etc). The result of executing the node is an instance ofSMutableArray
that encapsulates the array of evaluated expressions.Parser changes and a basic test has also been added.