Open Source Newspeak Code, and NS Implementations

280 views
Skip to first unread message

Stefan Marr

unread,
Apr 21, 2017, 3:09:44 PM4/21/17
to Newspeak Programming Language
Hi:

Since from time to time the issue comes up that SOMns isn't a 'proper' Newspeak (yet?), I was wondering whether there is somewhere a list of projects using Newspeak.
Or asked differently, how do I find Newspeak code (preferably open source)?

One way seems to be to search github for Newspeak3 (https://github.com/search?q=Newspeak3&type=Code&utf8=%E2%9C%93).
Any other ideas?

As far as implementations go, beside the standard one, I noticed the JS and Dart based ones.

Are there other ones I should be aware of?

Thanks
Stefan

Gilad Bracha

unread,
Apr 21, 2017, 3:22:59 PM4/21/17
to Newspeak Programming Language
Hi Stefan,

I think you've covered it. Vassil built some stuff to work on a vanilla JVM, but it is far from complete.

Wrt users: the only commercial user is Cadence, and that stuff is definitely not open source.

In terms of implementations: The Dart one is pretty much abandoned at this point.  NS2V8 is  the JS one, and still somewhat incomplete (mainly lacking some support for the more involved reflective changes) but alive and kicking. Psoup is advancing and has the advantage of being a pure, bootstrapped implementation. 

The best thing is to run the test suites. .  I'm also guessing that mirrors are lacking in SOMns, which means that Minitest won't run. And  this, I think you need to fix the grammar (i.e., do away with :=)  so you can parse any code you find.

I'd say that a minimal amount of mirror support so that one can run Minitest (this requires just limited introspection), some small grammar fixes an perhaps some tweaks to get the right compile interface  would be enough to see if you pass the language tests and declare SOMns a true Newspeak!

I may have some time in the next week or two, so I'm happy to help.


Gilad Bracha

unread,
Apr 21, 2017, 3:31:23 PM4/21/17
to Newspeak Programming Language
Of course, the test suites will only pass completely if you can do reflective changes.  But only the Smalltalk version fully supports that so far.

Stefan Marr

unread,
Apr 21, 2017, 4:09:49 PM4/21/17
to newspeak...@googlegroups.com
Hi Gilad:

> On 21 Apr 2017, at 21:22, Gilad Bracha <gbr...@gmail.com> wrote:
>
> I think you've covered it. Vassil built some stuff to work on a vanilla JVM, but it is far from complete.
>
> [..]

Thanks for the overview. Good to know.

> The best thing is to run the test suites. . I’m also guessing that mirrors are lacking in SOMns, which means that Minitest won't run.

I’ve actually been using a Minitest port since the beginning, including a fully asynchronous extension for testing actors:
https://github.com/smarr/SOMns-corelib/commits/master/TestSuite/Minitest.som

> And this, I think you need to fix the grammar (i.e., do away with :=) so you can parse any code you find.

Yes… It is on the todo list. I looked with Richard into it. It’s a trivial change and straightforward search replace for ‘ :=’ on the code we got. We’ll do it soon…

> I’d say that a minimal amount of mirror support so that one can run Minitest (this requires just limited introspection), some small grammar fixes an perhaps some tweaks to get the right compile interface would be enough to see if you pass the language tests and declare SOMns a true Newspeak!

I fear, that’s a bit further off. Especially to support proper intercession, run-time compilation of code, etc.
I hope some of the necessary infrastructure is going to be put in place with the Grace work, but that’s not going to happen in the next few weeks.

> I may have some time in the next week or two, so I’m happy to help.

Thanks, I was more curious about potential code I could try to run.
Just to know what’s out there, and whether I could use anything for experiments.

Best regards
Stefan

Ryan Macnak

unread,
Apr 24, 2017, 12:35:10 AM4/24/17
to newspeak...@googlegroups.com
On Fri, Apr 21, 2017 at 1:08 PM, Stefan Marr <goo...@stefan-marr.de> wrote:
Thanks, I was more curious about potential code I could try to run.
Just to know what’s out there, and whether I could use anything for experiments.

The benchmarks at https://bitbucket.org/newspeaklanguage/benchmarks are the most portable Newspeak code out there, as they don't use IO or UI. SOMns should be able to run them with minor tweaks.

The largest public Newspeak programs would be the IDE and compilers. The Newspeak-to-Javascript compiler would have the fewest Squeak dependencies and be easiest to get running on SOMns.

Stefan Marr

unread,
Jul 13, 2017, 10:38:29 AM7/13/17
to Newspeak Programming Language
Hi,

thanks for the pointers.

Now that I got setter sends (https://github.com/smarr/SOMns/pull/170),
I started looking at the benchmarks.
And it looks like there are a few more stumbling blocks.

Simple stuff:
 - SOMns doesn't support the Newspeak3 + Category syntax at the top of the file
 - it still doesn't have array literals/read-only tuples, but there is a patch
 - it doesn't support literal numbers with a base (16rCAFE), used in ParserCombinators
 - local variables with initialization syntax isn't supported yet

Not so trivial stuff:
 - ParserCombinators.ns uses type annotations, don't have support for that yet

Guess it will take some more parser work before I can run stuff.

Thanks
Stefan

Gilad Bracha

unread,
Jul 13, 2017, 10:55:51 AM7/13/17
to Newspeak Programming Language
Hi Stefan,

Thanks for the update. Type annotations are used in a lot of code; non-base 10 numbers not so much (maybe in our compiler). The other stuff is fairly common as well. Since types are ignored, you might be able to cheat by "diet-parsing" them by just matching up angle brackets.

Stefan Marr

unread,
Jul 13, 2017, 11:09:17 AM7/13/17
to newspeak...@googlegroups.com
Hi Gilad:

> On 13 Jul 2017, at 16:55, Gilad Bracha <gbr...@gmail.com> wrote:
>
> Thanks for the update. Type annotations are used in a lot of code; non-base 10 numbers not so much (maybe in our compiler). The other stuff is fairly common as well. Since types are ignored, you might be able to cheat by “diet-parsing" them by just matching up angle brackets.

I didn’t find the syntax for type annotations in the spec. Or is it identical with pattern literals?

Thanks
Stefan


Gilad Bracha

unread,
Jul 13, 2017, 11:19:22 AM7/13/17
to newspeak...@googlegroups.com
HI Stefan,

No, the type syntax is not at all related to the pattern literal experiment. We never put in the spec because someday I'd like to find a solution compatible with fully pluggable types, using metadata to store the type info.

The syntax is given in class TypedNS3Grammar, which is them used to override the regular grammar:


public class TypedNS3Grammar = NS3Grammar ((* A parser for Strongtalk syntax. Adds productions for the Strongtalk type expression sublanguage, and the changes needed to use types in Newsqueak code. *)|                   

arg = tokenFromSymbol: #arg.
for = tokenFromSymbol: #for.
generic = tokenFromSymbol: #generic.
inheritedTypeOf = tokenFromSymbol: #inheritedTypeOf.
is = tokenFromSymbol: #is.
mssg = tokenFromSymbol: #message.
of = tokenFromSymbol: #of.

receiverType = tokenFromSymbol: #receiverType.
subtypeOf = tokenFromSymbol: #subtypeOf.
typeArg = tokenFromSymbol: #typeArg.
where = tokenFromSymbol: #where.
returnType = hat, type.

(* Type Grammar *)

type = langleBracket, typeExpr, rangleBracket.
typePrimary = identifier, typeArguments opt.
typeFactor = typePrimary | blockType | tupleType | parenthesizedTypeExpression.
parenthesizedTypeExpression = lparen, typeExpr, rparen.
typeTerm = typeFactor, identifier star.
typeExpr = typeTerm, ((vbar | semicolon | slash), typeExpr) opt.
typeArguments = lbracket, (typeExpr plusSeparatedBy: comma), rbracket. 
tupleType = lcurly, (typeExpr starSeparatedBy: dot), rcurly.

  blockArgType = colon, typeTerm.
blockReturnType = typeExpr.
nonEmptyBlockArgList = blockArgType plus, (vbar, blockReturnType) opt.
blockType = lbracket, (nonEmptyBlockArgList | blockReturnType opt), rbracket.

(* Type inference *)

typePattern = langleBracket, typeFormal, (semicolon, typeFormal) star, rangleBracket. (* changed from {} to <> brackets to avoid conflict with tuples *)
typeFormal = where, identifier, typeParamConstraint opt, is, inferenceClause.
typeParamConstraint = langleBracket, typeBoundQualifier opt, typeExpr, rangleBracket.
typeBoundQualifier = subtypeOf | inheritedTypeOf.
inferenceClause = receiverType
| (returnType, returnTypeInferenceClause)
| typeArgInferenceClause
| (arg, number, (of, msgSelector) opt).
returnTypeInferenceClause = of, msgSelector.
msgSelector = symbolConstant, mssg, of, inferenceClause.
typeArgInferenceClause = typeArg, number, for, generic, symbolConstant, of, inferenceClause. 
 |) (
messagePattern = (
     ^super messagePattern, returnType opt, typePattern opt. (* Type annotations *)
)
slotDecl = (
    ^super slotDecl , type opt.
)
) : (
)

Stefan Marr

unread,
Jul 26, 2017, 9:39:30 AM7/26/17
to newspeak...@googlegroups.com
Hi Gilad,
Hi Ryan:

After adding various things to SOMns, and coercing the benchmarks a bit, I can run most of them.

To give an impression of what currently doesn’t really work as it does in Newspeak, see the changes here:
https://github.com/smarr/NewspeakBenchmarks/compare/SOMns

There are still some issues.
The closure benchmarks don’t stop compiling for some reason. Not exactly sure what’s going on there.
ParserCombinators will require character literals, which I haven’t implemented yet.
And wasn’t really planing on implementing, since they are marked as deprecated.

Generally, the benchmark harness isn’t ideal for highly optimizing VMs though.
So, numbers could be better with a different harness. I already increased the warmup time substantially, but the main problem remains: the ‘warmed up’, i.e., measuring run will trigger compilation, because a second block gets hot. Not ideal.

Anyway, numbers below.

Thanks for the pointers.

Best regards
Stefan


$ java BenchmarkRunner
MethodFibonacci 2852.500
DeltaBlue 5720.500
Richards 14261.000
Splay 492.500

$ dart-sdk-1.24.2/bin/dart BenchmarkRunner.dart
FieldRead: 17749.5 runs/second
FieldWrite: 18679.0 runs/second
SlotRead: 18813.0 runs/second
SlotWrite: 18606.5 runs/second
MethodFibonacci: 1952.5 runs/second
ClosureFibonacci: 705.0 runs/second
ClosureDefFibonacci: 228.8 runs/second
NLRImmediate: 336.7 runs/second
NLRLoop: 229.0 runs/second

DeltaBlue: 4425.5 runs/second
Richards: 8987.0 runs/second
Splay: 550.8 runs/second
ParserCombinators: 70.5 runs/second


$ ../SOMns/som BenchmarkRunner.som
SlotRead: 16159.2 runs/second
SlotWrite: 16251.0 runs/second
MethodFibonacci: 1522.8 runs/second
ClosureFibonacci: 16.1 runs/second
ClosureDefFibonacci: 0.6 runs/second
NLRImmediate: 157440.6 runs/second
NLRLoop: 33055.4 runs/second

DeltaBlue: 1707.3 runs/second
Richards: 5380.6 runs/second
Splay: 657.5 runs/second

With the GUIBenchmarkRunner on latest Newspeak
SlotRead: 224.7
SlotWrite: 298.0
MethodFibonacci: 704.5
ClosureFibonacci: 497.5
ClosureDefFibonacci: 176.5
NLRImmediate: 1322.0
NLRLoop: 830.0

DeltaBlue: 255.3
ParserCombinators: 37.0
Richards: 490.2
Splay: 175.5

Gilad Bracha

unread,
Jul 26, 2017, 12:22:57 PM7/26/17
to newspeak...@googlegroups.com
Hi Stefan,

This is great! I agree, you shouldn't bother with character literals; we should make progress on eliminating them. And we should review library differences and see if we can bridge that gap.

Ryan Macnak

unread,
Jul 26, 2017, 11:25:07 PM7/26/17
to newspeak...@googlegroups.com
On Wed, Jul 26, 2017 at 6:38 AM, Stefan Marr <goo...@stefan-marr.de> wrote:
Hi Gilad,
Hi Ryan:

After adding various things to SOMns, and coercing the benchmarks a bit, I can run most of them.

To give an impression of what currently doesn’t really work as it does in Newspeak, see the changes here:
https://github.com/smarr/NewspeakBenchmarks/compare/SOMns

There are still some issues.

The most glaring change to me is the global imports and global platform object in `system loadModule:`, which rather undermines the modularity story.
 
The closure benchmarks don’t stop compiling for some reason. Not exactly sure what’s going on there.
ParserCombinators will require character literals, which I haven’t implemented yet. 
And wasn’t really planing on implementing, since they are marked as deprecated.

I recommend implementing character literals as strings of length 1. Primordial Soup and the Dart and Javascript implementations do this. It's a very small cost for compatibility with code that also runs on the Squeak implementation. The benchmarks are all written so they work in implementations with strings and characters (legacy) and implementations that only have strings (per spec).

Generally, the benchmark harness isn’t ideal for highly optimizing VMs though.
So, numbers could be better with a different harness. I already increased the warmup time substantially, but the main problem remains: the ‘warmed up’, i.e., measuring run will trigger compilation, because a second block gets hot. Not ideal.

My experience lately in Dart-land is that benchmark harness is already far too biased in favor of VMs that are slow to warm up. High peak performance is not worth it in the client space if the cost is jank at application startup.
This is quite an improvement over Java. Do you implement non-local return in terms of exceptions? Has your compiler inlined the NLR away reducing this to a empty loop?
 
NLRLoop: 33055.4 runs/second

DeltaBlue: 1707.3 runs/second
Richards: 5380.6 runs/second
Splay: 657.5 runs/second

This is odd. Given Splay is GC-bound, I'd expect the Java and SOMns scores to be much closer together.

Stefan Marr

unread,
Jul 27, 2017, 4:37:52 AM7/27/17
to newspeak...@googlegroups.com
Hi Ryan:

> On 27 Jul 2017, at 05:25, Ryan Macnak <rma...@gmail.com> wrote:
>
> The most glaring change to me is the global imports

Global imports? Not sure what you are referring to.

> and global platform object in `system loadModule:`, which rather undermines the modularity story.

Global platform object? Not sure what you mean with that. The platform object isn’t global.
However, I see that your harness carefully avoids to access the platform object via the lexical scope, which seems to me like a performance optimization that ideally isn’t necessary.

For loading the benchmarks, I saw you use some `manifest` object instead. I am not sure however how that is constructed, and where it is coming from. Briefly greping over the code base didn't bring up anything immediately explanatory, but I probably mist it.

Where should be looking to see how it works?

> I recommend implementing character literals as strings of length 1.

Ok, parsing “c” to a string should be easy enough.
Thanks.

> My experience lately in Dart-land is that benchmark harness is already far too biased in favor of VMs that are slow to warm up. High peak performance is not worth it in the client space if the cost is jank at application startup.

Sure. However, Truffle+Graal on Hotspot is never going to have great startup/warmup. It will take them quite a while to reach their peak performance.

> This is quite an improvement over Java. Do you implement non-local return in terms of exceptions? Has your compiler inlined the NLR away reducing this to a empty loop?

NLR are implemented with exceptions yes, but they are optimized to simple jumps by Graal, and in the best case, it becomes an empty loop yes.

The reason why the closure benchmarks behave horrible is an unfortunate heuristic for splitting on the AST level.
This means, the AST never stabilizes, and therefore the compiler is always busy compiling but the code doesn’t execute for long enough.
Some more details here: http://markmail.org/thread/dg42ud652xr5rupf


>
> NLRLoop: 33055.4 runs/second
>
> DeltaBlue: 1707.3 runs/second
> Richards: 5380.6 runs/second
> Splay: 657.5 runs/second
>
> This is odd. Given Splay is GC-bound, I’d expect the Java and SOMns scores to be much closer together.

I didn’t look into details either.
But, I should run the Java versions with Graal instead of C2.
Graal applies partial escape analysis, which C2 doesn’t and it is much more aggressive about inlining. This could result in more objects being eliminated/not allocated in the first place.

Thanks
Stefan

Stefan Marr

unread,
Jul 27, 2017, 8:35:55 AM7/27/17
to newspeak...@googlegroups.com
Hi:

> On 26 Jul 2017, at 15:38, Stefan Marr <goo...@stefan-marr.de> wrote:
>
> $ dart-sdk-1.24.2/bin/dart BenchmarkRunner.dart
> ClosureFibonacci: 705.0 runs/second
> ClosureDefFibonacci: 228.8 runs/second
>
> $ ../SOMns/som BenchmarkRunner.som
> ClosureFibonacci: 16.1 runs/second
> ClosureDefFibonacci: 0.6 runs/second
>
> With the GUIBenchmarkRunner on latest Newspeak
> ClosureFibonacci: 497.5
> ClosureDefFibonacci: 176.5

And after working around the silly heuristic in Truffle (http://markmail.org/thread/dg42ud652xr5rupf),
I am seeing the following performance for the closure benchmarks:

ClosureFibonacci: 664.4 runs/second
ClosureDefFibonacci: 469.4 runs/second

Best regards
Stefan

Ryan Macnak

unread,
Aug 7, 2017, 10:45:11 PM8/7/17
to newspeak...@googlegroups.com
Hi Stefan,

Sorry for the slow reply.

On Thu, Jul 27, 2017 at 1:36 AM, Stefan Marr <goo...@stefan-marr.de> wrote:
Hi Ryan:

> On 27 Jul 2017, at 05:25, Ryan Macnak <rma...@gmail.com> wrote:
>
> The most glaring change to me is the global imports

Global imports? Not sure what you are referring to.

> and global platform object in `system loadModule:`, which rather undermines the modularity story.

Global platform object? Not sure what you mean with that. The platform object isn’t global.

Apologies, I incorrectly read loadModule as returning an module instance instead of a module definition.

However, I see that your harness carefully avoids to access the platform object via the lexical scope, which seems to me like a performance optimization that ideally isn’t necessary.

As a matter of style, we try to extract everything we need from the platform object up front. This makes it easier to see a module's dependencies, and avoids holding onto an unneeded capability.

For loading the benchmarks, I saw you use some `manifest` object instead. I am not sure however how that is constructed, and where it is coming from. Briefly greping over the code base didn't bring up anything immediately explanatory, but I probably mist it.

Where should be looking to see how it works?

The manifest provides access to the IDE's namespace at packaging time. For the Squeak implementation, it just forwards to the namespace. For the Javascript implementation, it records which modules need to be compiled, and well as which non-code resources should be packaged with the application. So `manifest Foo` is more-or-less your `system loadModule: 'Foo.ns'`.

Stefan Marr

unread,
Aug 8, 2017, 2:47:36 AM8/8/17
to newspeak...@googlegroups.com
Hi Ryan:

> On 8 Aug 2017, at 04:45, Ryan Macnak <rma...@gmail.com> wrote:
>
> Sorry for the slow reply.

No worries, and thank you :)

>> However, I see that your harness carefully avoids to access the platform object via the lexical scope, which seems to me like a performance optimization that ideally isn’t necessary.
>>
> As a matter of style, we try to extract everything we need from the platform object up front. This makes it easier to see a module’s dependencies, and avoids holding onto an unneeded capability.

Hm, I was actually thinking about something else, but I think I misread the code.
My modules get the platform directly, but yours got the manifest only, and then #main:args: gets the platform and eventually passes it to the benchmark.
I missed that the BenchmarkRunner didn’t get the platform object in the first place and found it curious that it is passed along explicitly.

> The manifest provides access to the IDE's namespace at packaging time. For the Squeak implementation, it just forwards to the namespace. For the Javascript implementation, it records which modules need to be compiled, and well as which non-code resources should be packaged with the application. So `manifest Foo` is more-or-less your `system loadModule: ‘Foo.ns'`.

Hm, ok. Well, in case of SOMns there’s no concept of “packaging time”. Guess, for the moment, I’ll leave it as it is.

Thanks
Stefan

Reply all
Reply to author
Forward
0 new messages