Language Size (was Re: [TLUG]: ECMAScript ("Javascript") Version 4 - FALSE ALARM)

# Maciej Stachowiak (18 years ago)

On Oct 30, 2007, at 1:01 PM, Chris Pine wrote:

Maciej Stachowiak wrote:

Can anyone address feasibility of a small full implementation
(source code all the way to execution)?

If we didn't think it was feasible, we wouldn't be here. :) While
we don't have a full implementation yet (no one does), progress is
looking good. Our latest engine, just out in Opera 9.5 beta, is
both smaller and considerably faster than our previous engine (which
we've shipped on many small devices). It runs on devices smaller
than an iPhone, no problem. (How much ram does an iPhone have? I
don't see that on Apple's site.)

Does your latest shipping engine implement parts of ES4? If so, how
much?

By the way, I think the discussions about language size could benefit
from some quantitative data. I think the following comparisons would
be interesting:

  1. Size of the ES4 grammar relative to the ES3 grammar (say, by count
    of productions).

  2. Size of the ES4 standard library by count of classes, methods and
    properties.

I am willing to run the number on these if someone can help me find
the grammar and some sort of standard library index in the spec.

, Maciej

# Jeff Dyer (18 years ago)

On 10/30/07 1:23 PM, Maciej Stachowiak wrote:

On Oct 30, 2007, at 1:01 PM, Chris Pine wrote:

Maciej Stachowiak wrote:

Can anyone address feasibility of a small full implementation (source code all the way to execution)?

If we didn't think it was feasible, we wouldn't be here. :) While we don't have a full implementation yet (no one does), progress is looking good. Our latest engine, just out in Opera 9.5 beta, is both smaller and considerably faster than our previous engine (which we've shipped on many small devices). It runs on devices smaller than an iPhone, no problem. (How much ram does an iPhone have? I don't see that on Apple's site.)

Does your latest shipping engine implement parts of ES4? If so, how much?

By the way, I think the discussions about language size could benefit from some quantitative data. I think the following comparisons would be interesting:

  1. Size of the ES4 grammar relative to the ES3 grammar (say, by count of productions).

  2. Size of the ES4 standard library by count of classes, methods and properties.

I am willing to run the number on these if someone can help me find the grammar and some sort of standard library index in the spec.

The grammar is posted at:

ecmacript.org/es4/spec/grammar.pdf

The builtin's are described in the a draft library spec in the monotone repository (./spec/library.pdf), which you should have access to.

Another interesting comparison is between ES3 and ES4 asts. There is a lot of syntactic sugar that get boiled out during parsing of ES4 programs. In fact, the same parse routines can be reused for different productions of the surface grammar. Compare the value syntax for objects and type syntax for record types, for example.

I'm happy to help put either document in a format that is easier to analyze.

# Jeff Dyer (18 years ago)

Fixed url of grammar.

# Thomas Reilly (18 years ago)

I'm sure! I wasn't being completely serious. We've learned that when you design something for the desktop its really hard to retrofit it for smaller devices, much better to start out small and tweak it to take advantage of the desktop's resource largesse. We also find that it almost never happens that way ;-) Given that my MacBookPro's kernel task is taking 200MB if my iphone is really running OS X then I'd say the Apple engineers did some serious squeezing to get the OS and applications/graphics all running in 128mb.

+1 on real language size/implementability discussions. Nothing more real, relevant and telling than having an es4 compiler written in es4 making use of as many language features as possible, luckily we're working just such a thing. How many lines of code is it? How much memory does it take to compile itself on the RI, on Tamarin? How fast can it compile itself? How big is the resulting abc?

Sure we'll start out with poor #'s and we can't even answer some of the questions but it'll be good to know where we're starting from.

I wish there was a language shootout page that tracked these metrics for platforms/languages with self hosting compilers. Does anyone have any ancedotal data?

# Chris Pine (18 years ago)

Maciej Stachowiak wrote:

On Oct 30, 2007, at 1:01 PM, Chris Pine wrote:

Maciej Stachowiak wrote:

Can anyone address feasibility of a small full implementation (source code all the way to execution)?

If we didn't think it was feasible, we wouldn't be here. :) While we don't have a full implementation yet (no one does), progress is looking good. Our latest engine, just out in Opera 9.5 beta, is both smaller and considerably faster than our previous engine (which we've shipped on many small devices). It runs on devices smaller than an iPhone, no problem. (How much ram does an iPhone have? I don't see that on Apple's site.)

Does your latest shipping engine implement parts of ES4? If so, how much?

Not much. Our first focus was to reduce and speed up what we have, to make room for the new features. And we are still not done with that; we can make this puppy smaller, yet.

  1. Size of the ES4 standard library by count of classes, methods and properties.

This really isn't changing much.

Chris

# Lars Hansen (18 years ago)

-----Original Message----- From: es4-discuss-bounces at mozilla.org On Behalf Of Maciej Stachowiak Sent: 30. oktober 2007 21:23

By the way, I think the discussions about language size could benefit from some quantitative data. I think the following comparisons would be interesting:

...

  1. Size of the ES4 standard library by count of classes, methods and properties.

Below is a breakdown of classes (C), interfaces (I), types (T), functions (F), methods (M), properties (P), variables/constants (V); * means new in ES4, + means it replaces something else in ES3 (typically a "primitive value"). "s" means "static", "p" means prototype. Based on current understanding; expect some minor adjustment over time.

Do not count lines uncritically. Where ES3 had prototype methods, ES4 has intrinsic methods in addition and sometimes generic static methods as well (Array, String, Function), but in almost all cases, only one of the set has a nontrivial body and the others delegate to it. Furthermore, many "String" methods delegate to "string" methods, and there are shared prototypes (String and String; byte, int, uint, double, decimal, and Number; boolean and Boolean). As a consequence, the footprint for the library is probably substantially smaller than it would appear at first glance. (Note also that [[Construct]] and [[Call]] have new names but are not new.)

--lars

  • V ECMASCRIPT_OBJECT [version number]

  • V ES4 [reserved namespace constant]

  • V ES4::intrinsic [reserved namespace constant]

  • V ES4::meta [reserved namespace constant]

  • V ES4::reflect [reserved namespace constant]

    C Object Ms Object Ms meta::invoke Vs length Vs prototype Mp toString Mp toLocaleString

  • Mp toJSONString Mp hasOwnProperty Mp isPrototypeOf Mp propertyIsEnumerable

  • M intrinsic::toString

  • M intrinsic::toLocaleString

  • M intrinsic::toJSONString

  • M intrinsic::hasOwnProperty

  • M intrinsic::isPrototypeOf

  • M intrinsic::propertyIsEnumerable

    C Function Ms Function Ms meta::invoke Vs length Vs prototype

  • Ms apply

  • Ms call M meta::invoke V length V prototype Mp toString Mp apply Mp call

  • M intrinsic::toString

  • M intrinsic::apply

  • M intrinsic::call

  • C ES4::GenericFunction [proposed, not fully spec'd]

    C Array Ms Array Ms meta::invoke Vs length

  • Ms concat

  • Ms every

  • Ms filter

  • Ms forEach

  • Ms indexOf

  • Ms join

  • Ms lastIndexOf

  • Ms map

  • Ms pop

  • Ms push

  • Ms reverse

  • Ms shift

  • Ms slice

  • Ms some

  • Ms sort

  • Ms splice

  • Ms unshift Mp concat Mp every Mp filter Mp forEach Mp indexOf Mp join Mp lastIndexOf Mp map Mp pop Mp push Mp reverse Mp shift Mp slice Mp some Mp sort Mp splice Mp unshift M get length M set length

  • M intrinsic::concat

  • M intrinsic::every

  • M intrinsic::filter

  • M intrinsic::forEach

  • M intrinsic::indexOf

  • M intrinsic::join

  • M intrinsic::lastIndexOf

  • M intrinsic::map

  • M intrinsic::pop

  • M intrinsic::push

  • M intrinsic::reverse

  • M intrinsic::shift

  • M intrinsic::slice

  • M intrinsic::some

  • M intrinsic::sort

  • M intrinsic::splice

  • M intrinsic::unshift

    C String Ms String Ms meta::invoke Vs length Ms fromCharCode

  • Ms charAt

  • Ms charCodeAt

  • Ms concat

  • Ms indexOf

  • Ms lastIndexOf

  • Ms localeCompare

  • Ms match

  • Ms parseJSON

  • Ms replace

  • Ms search

  • Ms slice

  • Ms split

  • Ms substring

  • Ms toLowerCase

  • Ms toLocaleLowerCase

  • Ms toUpperCase

  • Ms toLocaleUpperCase

  • Ms trim Mp charAt Mp charCodeAt Mp concat Mp indexOf Mp lastIndexOf Mp localeCompare Mp match Mp parseJSON Mp replace Mp search Mp slice Mp split Mp substring Mp toLowerCase Mp toLocaleLowerCase Mp toUpperCase Mp toLocaleUpperCase Mp trim M get length

  • M get

  • M intrinsic::charAt

  • M intrinsic::charCodeAt

  • M intrinsic::concat

  • M intrinsic::indexOf

  • M intrinsic::lastIndexOf

  • M intrinsic::localeCompare

  • M intrinsic::match

  • M intrinsic::parseJSON

  • M intrinsic::replace

  • M intrinsic::search

  • M intrinsic::slice

  • M intrinsic::split

  • M intrinsic::substring

  • M intrinsic::toLowerCase

  • M intrinsic::toLocaleLowerCase

  • M intrinsic::toUpperCase

  • M intrinsic::toLocaleUpperCase

  • M intrinsic::trim

  • C ES4::string
  • Ms string

  • Ms meta::invoke

  • Vs length

  • Ms fromCharCode

  • Ms charAt

  • Ms charCodeAt

  • Ms concat

  • Ms indexOf

  • Ms lastIndexOf

  • Ms localeCompare

  • Ms match

  • Ms parseJSON

  • Ms replace

  • Ms search

  • Ms slice

  • Ms split

  • Ms substring

  • Ms toLowerCase

  • Ms toLocaleLowerCase

  • Ms toUpperCase

  • Ms toLocaleUpperCase

  • Ms trim

  • M get length

  • M get

  • M intrinsic::charAt

  • M intrinsic::charCodeAt

  • M intrinsic::concat

  • M intrinsic::indexOf

  • M intrinsic::lastIndexOf

  • M intrinsic::localeCompare

  • M intrinsic::match

  • M intrinsic::parseJSON

  • M intrinsic::replace

  • M intrinsic::search

  • M intrinsic::slice

  • M intrinsic::split

  • M intrinsic::substring

  • M intrinsic::toLowerCase

  • M intrinsic::toLocaleLowerCase

  • M intrinsic::toUpperCase

  • M intrinsic::toLocaleUpperCase

  • M intrinsic::trim

    C Boolean Ms Boolean Ms meta::invoke Vs length Mp toString

  • Mp toJSONString Mp valueOf

  • M intrinsic::toString

  • M intrinsic::toJSONString

  • M intrinsic::valueOf

  • C ES4::boolean
  • Ms boolean

  • Ms meta::invoke

  • Vs length

  • M intrinsic::toString

  • M intrinsic::toJSONString

  • M intrinsic::valueOf

    C Number Ms Number Ms meta::invoke Vs length Vs MAX_VALUE Vs MIN_VALUE Vs NaN Vs NEGATIVE_INFINITY Vs POSITIVE_INFINITY Mp toString Mp toLocaleString

  • Mp toJSONString Mp valueOf Mp toFixed Mp toExponential Mp toPrecision M intrinsic::toString M intrinsic::toLocaleString

  • M intrinsic::toJSONString M intrinsic::valueOf M intrinsic::toFixed M intrinsic::toExponential M intrinsic::toPrecision

  • C ES4::byte Ms meta::invoke Vs length Vs MAX_VALUE Vs MIN_VALUE

  • C ES4::int

  • Ms int

  • Ms meta::invoke

  • Vs length

  • Vs MAX_VALUE

  • Vs MIN_VALUE

  • M intrinsic::toString

  • M intrinsic::toLocaleString

  • M intrinsic::toJSONString

  • M intrinsic::valueOf

  • M intrinsic::toFixed

  • M intrinsic::toExponential

  • M intrinsic::toPrecision

  • C ES4::uint

  • Ms uint

  • Ms meta::invoke

  • Vs length

  • Vs MAX_VALUE

  • Vs MIN_VALUE

  • M intrinsic::toString

  • M intrinsic::toLocaleString

  • M intrinsic::toJSONString

  • M intrinsic::valueOf

  • M intrinsic::toFixed

  • M intrinsic::toExponential

  • M intrinsic::toPrecision

  • C ES4::double
  • Ms double

  • Ms meta::invoke

  • Vs length

  • Vs MAX_VALUE

  • Vs MIN_VALUE

  • Vs NaN

  • Vs NEGATIVE_INFINITY

  • Vs POSITIVE_INFINITY

  • Vs E

  • Vs LN10

  • Vs LN2

  • Vs LOG2E

  • Vs LOG10E

  • Vs PI

  • Vs SQRT1_2

  • Vs SQRT2

  • M intrinsic::toString

  • M intrinsic::toLocaleString

  • M intrinsic::toJSONString

  • M intrinsic::valueOf

  • M intrinsic::toFixed

  • M intrinsic::toExponential

  • M intrinsic::toPrecision

  • C ES4::decimal

  • Ms int

  • Ms meta::invoke

  • Vs length

  • Vs MAX_VALUE

  • Vs MIN_VALUE

  • Vs NaN

  • Vs NEGATIVE_INFINITY

  • Vs POSITIVE_INFINITY

  • Vs E

  • Vs LN10

  • Vs LN2

  • Vs LOG2E

  • Vs LOG10E

  • Vs PI

  • Vs SQRT1_2

  • Vs SQRT2

  • M intrinsic::toString

  • M intrinsic::toLocaleString

  • M intrinsic::toJSONString

  • M intrinsic::valueOf

  • M intrinsic::toFixed

  • M intrinsic::toExponential

  • M intrinsic::toPrecision

    C Date Ms Date Ms meta::invoke

  • Ms intrinsic::parse

  • Ms intrinsic::UTC Ms now Vs parse Vs UTC Vs length Mp toString Mp toDateString Mp toTimeString Mp toLocaleString Mp toLocaleDateString Mp toLocaleTimeString Mp toUTCString

  • Mp toISOString

  • Mp toJSONString Mp valueOf Mp nanoAge Mp getTime Mp getFullYear Mp getUTCFullYear Mp getMonth Mp getUTCMonth Mp getDate Mp getUTCDate Mp getDay Mp getUTCDay Mp getHours Mp getUTCHours Mp getMinutes Mp getUTCMinutes Mp getSeconds Mp getUTCSeconds Mp getMilliseconds Mp getUTCMilliseconds Mp getTimezoneOffset Mp setTime Mp setMilliseconds Mp setUTCMilliseconds Mp setSeconds Mp setUTCSeconds Mp setMinutes Mp setUTCMinutes Mp setHours Mp setUTCHours Mp setDate Mp setUTCDate Mp setMonth Mp setUTCMonth Mp setFullYear Mp setUTCFullYear

  • M intrinsic::nanoAge

  • M intrinsic::toString

  • M intrinsic::toDateString

  • M intrinsic::toTimeString

  • M intrinsic::toLocaleString

  • M intrinsic::toLocaleDateString

  • M intrinsic::toLocaleTimeString

  • M intrinsic::toUTCString

  • M intrinsic::toISOString

  • M intrinsic::toJSONString

  • M intrinsic::valueOf

  • M intrinsic::getTime

  • M intrinsic::getFullYear

  • M intrinsic::getUTCFullYear

  • M intrinsic::getMonth

  • M intrinsic::getUTCMonth

  • M intrinsic::getDate

  • M intrinsic::getUTCDate

  • M intrinsic::getDay

  • M intrinsic::getUTCDay

  • M intrinsic::getHours

  • M intrinsic::getUTCHours

  • M intrinsic::getMinutes

  • M intrinsic::getUTCMinutes

  • M intrinsic::getSeconds

  • M intrinsic::getUTCSeconds

  • M intrinsic::getMilliseconds

  • M intrinsic::getUTCMilliseconds

  • M intrinsic::getTimezoneOffset

  • M intrinsic::setTime

  • M intrinsic::setMilliseconds

  • M intrinsic::setUTCMilliseconds

  • M intrinsic::setSeconds

  • M intrinsic::setUTCSeconds

  • M intrinsic::setMinutes

  • M intrinsic::setUTCMinutes

  • M intrinsic::setHours

  • M intrinsic::setUTCHours

  • M intrinsic::setDate

  • M intrinsic::setUTCDate

  • M intrinsic::setMonth

  • M intrinsic::setUTCMonth

  • M intrinsic::setFullYear

  • M intrinsic::setUTCFullYear

  • M get time

  • M get year

  • M get month

  • M get UTCMonth

  • M get date

  • M get UTCDate

  • M get day

  • M get UTCDay

  • M get hours

  • M get UTCHours

  • M get minutes

  • M get UTCMinutes

  • M get seconds

  • M get UTCSeconds

  • M get milliseconds

  • M get UTCMilliseconds

  • M set time

  • M set year

  • M set fullYear

  • M set UTCFullYear

  • M set month

  • M set UTCMonth

  • M set date

  • M set UTCDate

  • M set hours

  • M set UTCHours

  • M set minutes

  • M set UTCMinutes

  • M set seconds

  • M set UTCSeconds

  • M set milliseconds

  • M set UTCMilliseconds

    C RegExp Ms RegExp Ms meta::invoke Vs length Mp toString Mp exec Mp test

  • M meta::invoke

  • M intrinsic::toString

  • M intrinsic::exec

  • M intrinsic::test V source V global V ignoreCase V multiline

  • V extended

  • V sticky V lastIndex

    C Error Ms Error Ms meta::invoke Vs length V name V message

    C EvalError extends Error Ms EvalError Ms meta::invoke Vs length

    C RangeError extends Error Ms RangeError Ms meta::invoke Vs length

    C ReferenceError extends Error Ms ReferenceError Ms meta::invoke Vs length

    C SyntaxError extends Error Ms SyntaxError Ms meta::invoke Vs length

    C TypeError extends Error Ms TypeError Ms meta::invoke Vs length

    C URIError extends Error Ms URIError Ms meta::invoke Vs length

  • C ES4::EncodingError extends Error [for JSON]

  • Ms EncodingError

  • Ms meta::invoke

  • Vs length

  • C ES4::Name

  • Ms Name

  • Ms meta::invoke

  • Mp toString

  • Mp valueOf

  • M intrinsic::toString

  • M intrinsic::ValueOf

  • V qualifier

  • V identifier

  • C ES4::Namespace

  • Mp toString

  • M intrinsic::toString

  • C ES4::NamespaceSet [TBD -- small class]

  • C ES4::NamespaceSetList [TBD -- small class]

  • C ES4::Map.<K,V>

  • Ms Map

  • M intrinsic::size

  • M intrinsic::get

  • M intrinsic::put

  • M intrinsic::has

  • M intrinsic::remove

  • Mp size

  • Mp get

  • Mp put

  • M phas

  • Mp remove

  • M iterator::get

  • M iterator::getKeys

  • M iterator::getValues

  • M iterator::getItems

  • C ES4::Vector.<T>

  • Ms Vector

  • Ms meta::invoke

  • Vs length

  • Mp concat

  • Mp every

  • Mp filter

  • Mp forEach

  • Mp indexOf

  • Mp join

  • Mp lastIndexOf

  • Mp map

  • Mp pop

  • Mp push

  • Mp reverse

  • Mp shift

  • Mp slice

  • Mp some

  • Mp sort

  • Mp splice

  • Mp unshift

  • M get length

  • M set length

  • V fixed

  • M meta::get

  • M meta::set

  • M intrinsic::concat

  • M intrinsic::every

  • M intrinsic::filter

  • M intrinsic::forEach

  • M intrinsic::indexOf

  • M intrinsic::join

  • M intrinsic::lastIndexOf

  • M intrinsic::map

  • M intrinsic::pop

  • M intrinsic::push

  • M intrinsic::reverse

  • M intrinsic::shift

  • M intrinsic::slice

  • M intrinsic::some

  • M intrinsic::sort

  • M intrinsic::splice

  • M intrinsic::unshift

  • M iterator::get

  • M iterator::getKeys

  • M iterator::getValues

  • M iterator::getItems

  • C intrinsic::ControlInspector.<T> [may end up in

reflect::]

  • Ms ControlInspector

  • M annotate

  • M getCurrentAnnotation

  • M getAnnotation

  • T ES4::AnyNumber

  • T ES4::AnyString

  • T ES4::AnyBoolean

  • T ES4::EnumerableId

  • I reflect::Type

  • M canConvertTo

  • M isSubtypeOf

  • I reflect::NominalType

  • M name

  • M superTypes

  • M [a few more here, TBD]

  • I reflect::InterfaceType

  • M implementedBy

  • I reflect::ClassType

  • M construct

  • I reflect::AnyType

  • I reflect::NullType

  • I reflect::UndefinedType

  • I reflect::UnionType

  • M fields

  • M members

  • I reflect::RecordType

  • M construct

  • I reflect::FunctionType

  • M boundThid

  • M argTypes

  • M defaultValues

  • M hasRestType

  • M returnType

  • I reflect::ArrayType

  • M fields

  • M members

  • I reflect::ParameterizedType

  • I reflect::Field

  • M name

  • M type

  • I reflect::FieldValue

  • M name

  • M value

    F eval F parseInt F parseFloat F isNaN F isFinite F decodeURI F decodeURIComponent F encodeURI F encodeURIComponent

    V Math V E V LN10 V LN2 V LOG2E V LOG10E V PI V SQRT1_2 V SQRT2 M acos M atan M atan2 M ceil M cos M exp M floor M log M max M min M pow M random M round M sin M sqrt M tan

  • M intrinsic::acos

  • M intrinsic::atan

  • M intrinsic::atan2

  • M intrinsic::ceil

  • M intrinsic::cos

  • M intrinsic::exp

  • M intrinsic::floor

  • M intrinsic::log

  • M intrinsic::max

  • M intrinsic::min

  • M intrinsic::pow

  • M intrinsic::random

  • M intrinsic::round

  • M intrinsic::sin

  • M intrinsic::sqrt

  • M intrinsic::tan

    V NaN V Infinity V undefined

  • F intrinsic::eval

  • F intrinsic::parseInt

  • F intrinsic::parseFloat

  • F intrinsic::isNaN

  • F intrinsic::isFinite

  • F intrinsic::decodeURI

  • F intrinsic::decodeURIComponent

  • F intrinsic::encodeURI

  • F intrinsic::encodeURIComponent

  • V intrinsic::global

  • F reflect::typeOf

# Maciej Stachowiak (18 years ago)

On Oct 30, 2007, at 1:23 PM, Maciej Stachowiak wrote:

By the way, I think the discussions about language size could benefit from some quantitative data. I think the following comparisons would be interesting:

  1. Size of the ES4 grammar relative to the ES3 grammar (say, by count of productions).

Excluding the lexical grammar, the E4X syntax rules (which won't be a
normative requirement) and regular expression syntax, I count:

ECMA-262 3rd Edition: 74 grammar productions ECMAScript 4th edition draft: 197 grammar productions

That's a more than 2x increase in surface syntax (2.66x to be more
exact). While not completely unreasonable given all the new features,
it seems a little high. Before embarking on this exercise I thought
that 2x would be a reasonable level of core syntax increase. Part of
this may be simply due to better factoring of the grammar, and due to
capturing features like auto semicolon insertion, how if is
disambiguated, noin contexts, etc in more detail.

A lot of the genuinely new stuff just seems to be fallout from the
type system.

I notice some seemingly duplicate features that will perhaps become
more clear on closer reading of the spec. For instance I see all three
of namespace, package and unit productions in the grammar. With my
limited imagination it's hard to think of how those could be three
interestingly different features.

  1. Size of the ES4 standard library by count of classes, methods and properties.

I'll try to look at this soon, too. I think 4-5x would be about the
size that would not raise any red flags for me, given how impoverished
the ES3 standard library is.

Does anyone else have other ideas for objective metrics of language
size?

, Maciej

# Lars Hansen (18 years ago)

-----Original Message----- From: es4-discuss-bounces at mozilla.org [mailto:es4-discuss-bounces at mozilla.org] On Behalf Of Maciej Stachowiak Sent: 31. oktober 2007 11:47 To: Maciej Stachowiak Cc: es4-discuss; Steven Johnson; Chris Pine Subject: Re: Language Size (was Re: [TLUG]: ECMAScript ("Javascript") Version4 - FALSE ALARM)

Does anyone else have other ideas for objective metrics of language size?

Complexity of the implementation, certainly. Complexity of the semantics, maybe.

I joined TG1 in early 2006 as a representative of Opera (the position Chris Pine occupies now). My main concern was then to make sure the new language could be handled by an implementation that would just read source code off the wire and compile it in an on-line fashion, generating code as it went along, without building trees for anything more complex than expressions and without maintaining databases of compiler-only data. (I know for a fact this is possible for ES3, and it would be helpful to embedded implementations if it was also possible for ES4.) The language should be implementable by a system that could, as Graydon wrote the other day, evaluate everything lazily and not worry about a thing until it couldn't put them off any longer, just like the case is for ES3.

(A fallout of that (my victory or my fault, depending on how you see it) is that ES4 does not require things like definite assignment analysis, which would have required more elaborate data structures than a compiler on an embedded system would be happy with. Instead we have a syntactic workaround (the "settings" section of the constructor) and other rules to handle non-nullability. Kludgy? Depends on your point of view. My view is that embedded is a prime target for the language, and we adapt accordingly. Until most phones have fast CPUs and a lot of RAM, embedded is hard.)

I still think that ES4 can be compiled that way, classes and packages and parameterized types and all. And I do think that says something about the relatively low complexity of the language and how fit it is for difficult environments.

(In fairness, we don't know yet how well a commercial implementation can do on-line compilation under the pressure of performance requirements both for the compiler and for the compiled code, but I have confidence, based on no little experience from ES3, that it will be fine.)

# Yehuda Katz (18 years ago)

---------- Forwarded message ---------- From: Yehuda Katz <wycats at gmail.com>

Date: Oct 31, 2007 3:58 AM Subject: Re: Language Size (was Re: [TLUG]: ECMAScript ("Javascript") Version 4 -FALSE ALARM) To: Lars Hansen <lhansen at adobe.com>

A massive chunk of these are the duplicate methods in the intrinsic namespace. If you remove those, you actually have very few new classes or methods (see below). Another big chunk is getters and setters that represent old ES3 methods pre-getters and setters.

Specifically, removing the duplicate intrinsic methods (but not removing replacing getters/setters, etc.), there are 256 new items on this list, vs. 276 old methods. Hardly "bloated".

  • V ECMASCRIPT_OBJECT [version number]
  • V ES4 [reserved namespace constant]
  • V ES4::intrinsic [reserved namespace constant]
  • V ES4::meta [reserved namespace constant]
  • V ES4::reflect [reserved namespace constant]

C Object Ms Object Ms meta::invoke Vs length Vs prototype Mp toString Mp toLocaleString

  • Mp toJSONString Mp hasOwnProperty Mp isPrototypeOf Mp propertyIsEnumerable

C Function Ms Function Ms meta::invoke Vs length Vs prototype

  • Ms apply

  • Ms call M meta::invoke V length V prototype Mp toString Mp apply Mp call

  • C ES4::GenericFunction [proposed, not fully spec'd]

C Array Ms Array Ms meta::invoke Vs length

  • Ms concat
  • Ms every
  • Ms filter
  • Ms forEach
  • Ms indexOf
  • Ms join
  • Ms lastIndexOf
  • Ms map
  • Ms pop
  • Ms push
  • Ms reverse
  • Ms shift
  • Ms slice
  • Ms some
  • Ms sort
  • Ms splice
  • Ms unshift Mp concat Mp every Mp filter Mp forEach Mp indexOf Mp join Mp lastIndexOf Mp map Mp pop Mp push Mp reverse Mp shift Mp slice Mp some Mp sort Mp splice Mp unshift M get length M set length

C String Ms String Ms meta::invoke Vs length Ms fromCharCode

  • Ms charAt
  • Ms charCodeAt
  • Ms concat
  • Ms indexOf
  • Ms lastIndexOf
  • Ms localeCompare
  • Ms match
  • Ms parseJSON
  • Ms replace
  • Ms search
  • Ms slice
  • Ms split
  • Ms substring
  • Ms toLowerCase
  • Ms toLocaleLowerCase
  • Ms toUpperCase
  • Ms toLocaleUpperCase
  • Ms trim Mp charAt Mp charCodeAt Mp concat Mp indexOf Mp lastIndexOf Mp localeCompare Mp match Mp parseJSON Mp replace Mp search Mp slice Mp split Mp substring Mp toLowerCase Mp toLocaleLowerCase Mp toUpperCase Mp toLocaleUpperCase Mp trim M get length
  • C ES4::string
  • Ms string
  • Ms meta::invoke
  • Vs length
  • Ms fromCharCode
  • Ms charAt
  • Ms charCodeAt
  • Ms concat
  • Ms indexOf
  • Ms lastIndexOf
  • Ms localeCompare
  • Ms match
  • Ms parseJSON
  • Ms replace
  • Ms search
  • Ms slice
  • Ms split
  • Ms substring
  • Ms toLowerCase
  • Ms toLocaleLowerCase
  • Ms toUpperCase
  • Ms toLocaleUpperCase
  • Ms trim
  • M get length
  • M get

C Boolean Ms Boolean Ms meta::invoke Vs length Mp toString

  • Mp toJSONString Mp valueOf
  • C ES4::boolean
  • Ms boolean
  • Ms meta::invoke
  • Vs length

C Number Ms Number Ms meta::invoke Vs length Vs MAX_VALUE Vs MIN_VALUE Vs NaN Vs NEGATIVE_INFINITY Vs POSITIVE_INFINITY Mp toString Mp toLocaleString

  • Mp toJSONString Mp valueOf Mp toFixed Mp toExponential Mp toPrecision

  • C ES4::byte Ms meta::invoke Vs length Vs MAX_VALUE Vs MIN_VALUE

  • C ES4::int

  • Ms int

  • Ms meta::invoke

  • Vs length

  • Vs MAX_VALUE

  • Vs MIN_VALUE

  • C ES4::uint

  • Ms uint

  • Ms meta::invoke

  • Vs length

  • Vs MAX_VALUE

  • Vs MIN_VALUE

  • C ES4::double
  • Ms double

  • Ms meta::invoke

  • Vs length

  • Vs MAX_VALUE

  • Vs MIN_VALUE

  • Vs NaN

  • Vs NEGATIVE_INFINITY

  • Vs POSITIVE_INFINITY

  • Vs E

  • Vs LN10

  • Vs LN2

  • Vs LOG2E

  • Vs LOG10E

  • Vs PI

  • Vs SQRT1_2

  • Vs SQRT2

  • C ES4::decimal

  • Ms int

  • Ms meta::invoke

  • Vs length

  • Vs MAX_VALUE

  • Vs MIN_VALUE

  • Vs NaN

  • Vs NEGATIVE_INFINITY

  • Vs POSITIVE_INFINITY

  • Vs E

  • Vs LN10

  • Vs LN2

  • Vs LOG2E

  • Vs LOG10E

  • Vs PI

  • Vs SQRT1_2

  • Vs SQRT2

C Date Ms Date Ms meta::invoke Ms now Vs parse Vs UTC Vs length Mp toString Mp toDateString Mp toTimeString Mp toLocaleString Mp toLocaleDateString Mp toLocaleTimeString Mp toUTCString

  • Mp toISOString
  • Mp toJSONString Mp valueOf Mp nanoAge Mp getTime Mp getFullYear Mp getUTCFullYear Mp getMonth Mp getUTCMonth Mp getDate Mp getUTCDate Mp getDay Mp getUTCDay Mp getHours Mp getUTCHours Mp getMinutes Mp getUTCMinutes Mp getSeconds Mp getUTCSeconds Mp getMilliseconds Mp getUTCMilliseconds Mp getTimezoneOffset Mp setTime Mp setMilliseconds Mp setUTCMilliseconds Mp setSeconds Mp setUTCSeconds Mp setMinutes Mp setUTCMinutes Mp setHours Mp setUTCHours Mp setDate Mp setUTCDate Mp setMonth Mp setUTCMonth Mp setFullYear Mp setUTCFullYear
  • M get time
  • M get year
  • M get month
  • M get UTCMonth
  • M get date
  • M get UTCDate
  • M get day
  • M get UTCDay
  • M get hours
  • M get UTCHours
  • M get minutes
  • M get UTCMinutes
  • M get seconds
  • M get UTCSeconds
  • M get milliseconds
  • M get UTCMilliseconds
  • M set time
  • M set year
  • M set fullYear
  • M set UTCFullYear
  • M set month
  • M set UTCMonth
  • M set date
  • M set UTCDate
  • M set hours
  • M set UTCHours
  • M set minutes
  • M set UTCMinutes
  • M set seconds
  • M set UTCSeconds
  • M set milliseconds
  • M set UTCMilliseconds

C RegExp Ms RegExp Ms meta::invoke Vs length Mp toString Mp exec Mp test

  • M meta::invoke V source V global V ignoreCase V multiline
  • V extended
  • V sticky V lastIndex

C Error Ms Error Ms meta::invoke Vs length V name V message

C EvalError extends Error Ms EvalError Ms meta::invoke Vs length

C RangeError extends Error Ms RangeError Ms meta::invoke Vs length

C ReferenceError extends Error Ms ReferenceError Ms meta::invoke Vs length

C SyntaxError extends Error Ms SyntaxError Ms meta::invoke Vs length

C TypeError extends Error Ms TypeError Ms meta::invoke Vs length

C URIError extends Error Ms URIError Ms meta::invoke Vs length

  • C ES4::EncodingError extends Error [for JSON]

  • Ms EncodingError

  • Ms meta::invoke

  • Vs length

  • C ES4::Name

  • Ms Name

  • Ms meta::invoke

  • Mp toString

  • Mp valueOf

  • V qualifier

  • V identifier

  • C ES4::Namespace

  • Mp toString

  • C ES4::NamespaceSet [TBD -- small class]

  • C ES4::NamespaceSetList [TBD -- small class]

  • C ES4::Map.<K,V>

  • Ms Map

  • Mp size

  • Mp get

  • Mp put

  • M phas

  • Mp remove

  • M iterator::get

  • M iterator::getKeys

  • M iterator::getValues

  • M iterator::getItems

  • C ES4::Vector.<T>

  • Ms Vector

  • Ms meta::invoke

  • Vs length

  • Mp concat

  • Mp every

  • Mp filter

  • Mp forEach

  • Mp indexOf

  • Mp join

  • Mp lastIndexOf

  • Mp map

  • Mp pop

  • Mp push

  • Mp reverse

  • Mp shift

  • Mp slice

  • Mp some

  • Mp sort

  • Mp splice

  • Mp unshift

  • M get length

  • M set length

  • V fixed

  • M meta::get

  • M meta::set

  • M iterator::getKeys

  • M iterator::getValues

  • M iterator::getItems

  • C intrinsic::ControlInspector.<T> [may end up in reflect::]

  • Ms ControlInspector

  • M annotate

  • M getCurrentAnnotation

  • M getAnnotation

  • T ES4::AnyNumber

  • T ES4::AnyString

  • T ES4::AnyBoolean

  • T ES4::EnumerableId

  • I reflect::Type

  • M canConvertTo

  • M isSubtypeOf

  • I reflect::NominalType

  • M name

  • M superTypes

  • M [a few more here, TBD]

  • I reflect::InterfaceType

  • M implementedBy

  • I reflect::ClassType

  • M construct

  • I reflect::AnyType

  • I reflect::NullType

  • I reflect::UndefinedType

  • I reflect::UnionType

  • M fields

  • M members

  • I reflect::RecordType

  • M construct

  • I reflect::FunctionType

  • M boundThid

  • M argTypes

  • M defaultValues

  • M hasRestType

  • M returnType

  • I reflect::ArrayType

  • M fields

  • M members

  • I reflect::ParameterizedType

  • I reflect::Field

  • M name

  • M type

  • I reflect::FieldValue

  • M name

  • M value

F eval F parseInt F parseFloat F isNaN F isFinite F decodeURI F decodeURIComponent F encodeURI F encodeURIComponent

V Math V E V LN10 V LN2 V LOG2E V LOG10E V PI V SQRT1_2 V SQRT2 M acos M atan M atan2 M ceil M cos M exp M floor M log M max M min M pow M random M round M sin M sqrt M tan

V NaN V Infinity V undefined

  • F reflect::typeOf
# Maciej Stachowiak (18 years ago)

On Oct 31, 2007, at 4:28 AM, Yehuda Katz wrote:

---------- Forwarded message ---------- From: Yehuda Katz <wycats at gmail.com> Date: Oct 31, 2007 3:58 AM Subject: Re: Language Size (was Re: [TLUG]: ECMAScript
("Javascript") Version 4 -FALSE ALARM) To: Lars Hansen <lhansen at adobe.com>

A massive chunk of these are the duplicate methods in the intrinsic
namespace. If you remove those, you actually have very few new
classes or methods (see below). Another big chunk is getters and
setters that represent old ES3 methods pre-getters and setters.

Specifically, removing the duplicate intrinsic methods (but not
removing replacing getters/setters, etc.), there are 256 new items
on this list, vs. 276 old methods. Hardly "bloated".

That doesn't exactly match my count, but close enough. For ES4 I
removed all duplicate intrinsic:: names (not sure what these are for
but I'll trust that they are not interestingly different), one of the
two String classes, and meta::invoke. For ES3 I did not count [[Call]]
internal properties or the like. I get:

ES3: 220 ES4: 437

Seems to be about the same ~2x increase that you report, though we
used different methodologies to count. I would not count this as
excessive growth, when it comes to the standard library.

, Maciej

# Harri Porten (18 years ago)

On Wed, 31 Oct 2007, Maciej Stachowiak wrote:

Does anyone else have other ideas for objective metrics of language size?

"Compilation time" - of course not that objective as heavily implementation specific but still an indicator for the complexity of the language :)

But seriously: from my own work on an ES4 interpreter (based on the previous draft back then) I saw the biggest impact on the implementation to be in the "compilation phase". This went hand in the hand with the advantages of the type system, i.e. the possibility to apply optimizations before execution.

In my personal book I therefore judge the complexity of a language also based on the observation whether runtime implementations typically include a compiler, i.e. offer an eval() function or not.

Harri.

# Maciej Stachowiak (18 years ago)

On Oct 31, 2007, at 4:45 AM, Harri Porten wrote:

Hi!

On Wed, 31 Oct 2007, Maciej Stachowiak wrote:

Does anyone else have other ideas for objective metrics of language size?

"Compilation time" - of course not that objective as heavily implementation specific but still an indicator for the complexity of
the language :)

But seriously: from my own work on an ES4 interpreter (based on the previous draft back then) I saw the biggest impact on the
implementation to be in the "compilation phase". This went hand in the hand with the advantages of the type system, i.e. the possibility to apply optimizations before execution.

In my personal book I therefore judge the complexity of a language
also based on the observation whether runtime implementations typically
include a compiler, i.e. offer an eval() function or not.

Specifically comparing ES4 to ES3, I would hope for no significant
increase in compilation time if one is willing to accept that there
won't be much improvement in execution time. I am not sure if this is
a reasonable expectation based on the spec, but it seems like many on
the committee share roughly similar goals.

# Yehuda Katz (18 years ago)

Incidentally, a fair but of what remains is Time getters/setters and the group of AnyNumber classes. If no one has done it by then, I'll do a chart of the largest groupings in the morning.

# Dave Herman (18 years ago)

(A fallout of that (my victory or my fault, depending on how you see it) is that ES4 does not require things like definite assignment analysis, which would have required more elaborate data structures than a compiler on an embedded system would be happy with. Instead we have a syntactic workaround (the "settings" section of the constructor) and other rules to handle non-nullability. Kludgy? Depends on your point of view.

As an aside: in my view this design goal ("no complex static analyses in the semantics") is not just a win for lightweight devices. It's also a win for the simplicity of the semantics. A programmer doesn't have to think about complex analyses to understand the meaning of a program; similarly, when the compiler/interpreter freaks out because an analysis failed, the programmer doesn't have to understand a complicated error. Syntactic restrictions like lexical scope, the "settings" section, type systems, etc. have the benefit of being based on simple syntactic properties that are easy for the programmer to eyeball by inspection of the source. The result is a cleaner and clearer language semantics.

# Lars Hansen (18 years ago)

The intrinsic names are for early binding. Since the prototypes are mutable nothing is known about their properties. So code that wishes to early-bind to methods would annotate its variables and open the intrinsic namespace to give preference to intrinsic methods over prototype methods. The benefits are performance, known semantics, and static type checking (in strict mode).

And you are right, they are not interestingly different: they have type annotations. (Usually, the prototype method calls the intrinsic method after performing type conversions mandated by ES3. There are a few wrinkles here and there but nothing important.)

# Brendan Eich (18 years ago)

On Oct 31, 2007, at 5:42 AM, Lars Hansen wrote:

The intrinsic names are for early binding. Since the prototypes
are mutable nothing is known about their properties. So code that
wishes to early-bind to methods would annotate its variables and
open the intrinsic namespace to give preference to intrinsic
methods over prototype methods. The benefits are performance,
known semantics, and static type checking (in strict mode).

And you are right, they are not interestingly different: they have
type annotations. (Usually, the prototype method calls the
intrinsic method after performing type conversions mandated by
ES3. There are a few wrinkles here and there but nothing important.)

I changed the subject so it may have been missed, but most of what I
wrote at

mail.mozilla.org/pipermail/es4-discuss/2007-October/001415.html

which built on Graydon's message at

mail.mozilla.org/pipermail/es4-discuss/2007-October/001408.html

was about intrinsic. Hope it helps,

# Brendan Eich (18 years ago)

On Oct 31, 2007, at 4:45 AM, Harri Porten wrote:

But seriously: from my own work on an ES4 interpreter (based on the previous draft back then) I saw the biggest impact on the
implementation to be in the "compilation phase". This went hand in the hand with the advantages of the type system, i.e. the possibility to apply optimizations before execution.

(Just want to reconfirm that none of these analyses for optimization
or any other reason are required. Also, FWIW, the more we look at JS
optimization the more runtime techniques seem to do better; we
haven't looked at agressive ahead of time compilation techniques of
course.)

In my personal book I therefore judge the complexity of a language
also based on the observation whether runtime implementations typically
include a compiler, i.e. offer an eval() function or not.

ES4 requires eval, as ES3 did. We're not sure what will become of the
ES3 compact profile (www.ecma-international.org/publications standards/Ecma-327.htm), but it is a bit of a flop on anything web- connected. I don't see the need to leave out eval. Flash does
implement the compact profile, but from the self-hosted ES4 compiler
that Jeff Dyer has built on top of Tamarin, it looks like Flash will
have eval too.

# Brendan Eich (18 years ago)

On Oct 31, 2007, at 3:46 AM, Maciej Stachowiak wrote:

I notice some seemingly duplicate features that will perhaps become more clear on closer reading of the spec. For instance I see all three of namespace, package and unit productions in the grammar. With my limited imagination it's hard to think of how those could be three interestingly different features.

What's the Sesame Street song? "... one of these things is not like
the other, one of these things just doesn't belong."

You are not alone in wondering about these three -- this has come up
at past TG1 meetings and we went ahead and implemented to get
experience. Michael O'Brien has a small-device implementation that
he's posted about here. He may have useful feedback.

This may help separate namespaces and units:

  • A namespace is a qualifier on property name (a string in general in
    ES1-3). It's a prefix to apply to unqualified identifiers used by a
    block in which a 'use namespace N' pragma occurs at the top. There
    are sane rules about ordering and ambiguity errors, covered briefly
    in the overview. As you can see from the RI, namespaces are used
    heavily. One benefit is to avoid incompatible name pollution of
    unqualified identifiers in the standard objects and the global object.

  • A program unit is an explicit reflection of the Program
    production's semantics from ES1-3. When you see a program unit body's
    closing brace, the steps in ES3 Chapter 10.2, plus ES4 steps like
    those, kick in. You can nest units, and a server framework can expand
    them server side when they are stated without bodies, but with
    locators that point to the body in question. This preserves accurate
    source coordinates for errors coming from nested units, and avoids
    downloading too many small files. See the proposal for more detail.

These two are genuinely different, orthogonal, and useful things, I
think.

  • Packages are built on namespaces, and unlike program units they are
    open-ended. You can keep adding to a package (someone correct me if
    I'm wrong), by writing

package acme.widgets { ... }

several times in a row. As the overview notes, a package has two
namespaces, package-public and package-internal. There's an import
directive for pulling some or all of the public names of a package
into another scope.

# Michael O'Brien (18 years ago)

An HTML attachment was scrubbed... URL: esdiscuss/attachments/20071031/8f78d3e0/attachment-0002

# Brendan Eich (18 years ago)

Yes, good points:

  • Packages de-sugar to namespaces, pragmas, and a missing primitive
    akin to gensym, to make the unforgeable package-public and package- internal namespaces. They're almost totally syntactic conveniences.

  • Along with reflecting the Program production's semantics, program
    units allow programmers to express and check dependencies -- the two
    forms: unit reference, 'use unit [locator]'; and unit provision 'use
    unit [locator] { body }', are the familiar require/provide verbs from
    other languages. This is a critical missing feature from ES1-3.

# Jeff Dyer (18 years ago)

I made an attempt to size the ES3 and ES4 grammars by assigning an ES edition number to each production, sorting and counting both concrete and abstract forms. Below are the numbers I came up with. This are very rough, but having implemented parsers for ES3, AS3 and ES4, the ~2x increase in number of productions feels about right.

             ES3   ES4
             ---   ---

Concrete 238 490 Type Exprs 50 Classes & Interfaces 23 Patterns 17

Abstract 33 77

Methodology:

1/sort grammar productions and AST constructors by version 2/count concrete productions for each version 3/sort grammar productions by AST constructor 4/eliminate duplicate constructors 5/sort AST constructors by version 6/count AST constructors for each version

The spreadsheet I used is posted in PDF and XLS formats here:

ecmascript.org/es4/spec/grammar.pdf, ecmascript.org/es4/spec/grammar.xls