[Ohrrpgce] Gradual (optional static) typing for HamsterSpeak

James Paige Bob at hamsterrepublic.com
Tue Aug 23 11:29:11 PDT 2016


Wow! The suggestion of static typing instead of python-style dynamic typing
surprised me, but after carefully reading your argument for it, I think I
agree. I trust your judgment on this, and it seems like it will actually
make forwards/backwards compatibility easier, and the inclustion of the Any
type means I can still do as much dynamic typing nonsense as I please :)

I like the idea of having Number as the default type instead of Any.

As for declaration syntax... after reading all those I think cast my first
vote for something like:

script, <Slice> return me some slice, <String> string arg, <Attack> attack
arg, begin

But I could live with many of the other syntaxes you suggested, I just
think this one looks cleanest to me.

I also dislike the idea of being flexible about whether the type comes
before or after. Just because <bracketing> makes it possible, doesn't mean
it is a good idea.

Bonus argument in favor of <Typename> is that Mogri turned off html by
default in forum posts so we could actually use <Typename> without
copy-paste agony ;)

---
James "Feeling Pretty Excited About This" Paige


On Tue, Aug 23, 2016 at 10:45 AM, Ralph Versteegen <teeemcee at gmail.com>
wrote:

> I'm finally resuming work on designing and implementing the major new
> version of HamsterSpeak (which I call HS4) which adds types and object
> orientation, while being backwards-compatible.  I'm looking for
> feedback in the design of the language. This email discusses the type
> system and specifically how type annotations might work.
>
> May as well state that the main goals of HS4 are:
> - Easy to learn. Should be:
> -- as simple as possible
> -- similar to popular languages
> -- consistent, including with existing HS idioms
> - Easy to use:
> -- features you expect in modern languages, like arrays, dicts and
>    strings with various handy methods
> -- easy to avoid bugs and to debug
> -- features useful for scripting games (hooks and extensible builtin
>    objects, script fibres, signalable and pauseable scripts (e.g. tied
>    to an npc or map), and live-reloading of scripts)
> - Backwards compatibility
> -- it's OK if a couple features are toggled off with backcompat
>    bitsets or other means, most notably necessary for script
>    'multitasking', but existing scripts should not need modifying
>    except in exceptional cases (e.g. new keywords)
>
>
> For years, the plan has been for HS4 to be a dynamically typed
> language, but in the intervening years I've been using Python and
> other dynamic languages heavily, and as a result now really appreciate
> what a great thing static typing is, for catching bugs and improving
> code readability.
>
> If we add OO methods as alternatives to existing functions then
>  set slice velocity(sl, 10, 10, 5)
> could be written
>  sl.set velocity(10, 10, 5)
> Then what happens if you typo the function/method name or pass invalid
> arguments?  Currently HSpeak can catch typo'd names and at least check
> the number of arguments.  But if everything is dynamic, the typo
> wouldn't be detected until you run the script. This would be a huge
> step backwards. The goal is to help users eliminate bugs (people
> frequently pass invalid arguments to commands, like mixing up hero IDs
> and party slots), but we would be encouraging them.
>
> Therefore I propose adding syntax to declare the types of variables
> (including locals, globals, and builtin command and script arguments
> and return values), and that builtin types/classes and user defined
> types (UDTs) be statically defined in a hss/hsd file.  Then HSpeak
> will be able to verify that accessed methods and members actually
> exist, and would also be able to check that sensible arguments are
> passed to scripts, which will catch a large class of bugs.  There will
> also be an 'any' type, which prevents type checking but lets you do
> whatever you want at runtime.  I recommend that variables that aren't
> annotated with a type default to 'number' instead of 'any', so that
> you have to explicitly ask for dynamic typing. Otherwise people will
> default to not declaring types for anything, and thus would be
> susceptible to bugs.
>
> I'm not proposing a rich strict type system lets you be type-safe all
> the time.  That means no "algebraic" nested type expressions such as
> templates/generics (parametrised types) or C's function pointer types
> which specify argument types.  Well, as an exception, it would be nice
> to also support a more refined 'array(attack)' type, although the
> 'array' type would simply default to an array of 'any'.  Calling
> callbacks (function types) is uncommon, so typing them seems unnecessary.
>
> I also propose being lenient with type conversions so that there's no
> need to use explicit casts (or to even add them to the language):
>  - Clearly all types should automatically convert to an 'any' variable
>  - An 'any' value could automatically convert to anything else
>  - All existing script commands that expect ID numbers or handles work
>    with objects too, and vice-versa.
> Maybe we could even also implicitly convert integers into types for
> builtin objects with ID numbers, e.g.:
>   variable([attack] atk)   # See below about declaration syntax
>   atk := 3
>   show string(atk.name)
> This looks a bit evil, but a more realistic example why you might want
> such a thing is:
>   script, npc dances, [npc] who, ( ... )
>   ...
>   npc dances(3)  # First NPC with ID 3
> Or if not, just require an explicit like "atk := get attack(3)".
> I'm leaning towards that, but also want the autoconversion in the
> second example, and don't know how to reconcile them.
>
> If type definitions are static then polymorphism requires inheritance
> (probably explicitly declared ("nominal" rather than "structural")).
> Unless you just use 'any', of course. It could also be possible to
> allow adding new members and methods to objects via an 'any'
> variable. Of course, then you have no error checking at run-time
> either, so something more explicit than "x.y := z" could maybe be
> required.
>
> ==Syntax==
>
> I can't actually decide on the syntax for declaring types, which is
> not easy to decide because of white-space insensitivity.  I also want
> to avoid any use of commas or parentheses, which would be confusing
> and likely ambiguous in script argument lists.  Also, note that we
> will want builtin types like 'npc', 'item', 'hero', etc.  Since these
> are all very common variable names, type names would have to live in a
> separate namespace (like in FreeBasic) and the type ought to stand out
> when written. Alternatively (although not entirely different) type
> names could start/end with a special character, such as "!Hero".
> Capitalising type names by convention would also help.
>
> Broadly, some different options are:
> (recall I suggested 'Number' be the default, hence optional)
> - variablename separator typename
>    script, dup item, item !Item, times !Number = 1, begin
>    # Julia uses the following
>    script, dup item, item ::Item, times ::Number = 1, begin
>    script, dup item, item *Item, times *Number = 1, begin
>    script, dup item, item -> Item, times -> Number = 1, begin
> - typename separator variablename
> -- e.g.
>    script, dup item, Item! item, Number! times = 1, begin
>    script, dup item, Item:: item, Number:: times = 1, begin
>    script, dup item, Item/ item, Number/ times = 1, begin
>    script, dup item, Item.item, Number.times = 1, begin
> - bracketed-typename variablename  (or the reverse)
> -- e.g.
>    script, dup item, [item] item, [number] times = 1, begin
>    script, dup item, /item/ item, /number/ times = 1, begin
>    script, dup item, <item> item, <number> times = 1, begin
>    script, dup item, "item" item, "number" times = 1, begin
>    Note that in this case we could allow putting the type before or
>    after as you wish (then you don't need to remember where it goes)!
> - something that looks like a keyword
> -- e.g.
>    script, dup item, item .is Item, times .is Number = 1, begin
>      As a bonus, "is XYZ" could be actual methods/functions for checking
> type:
>      if (x.is number) then (...)  # Seems to imply everything-is-an-object
>                                   # even if that's not the case.
>      if (is number(x)) then (...)
>    script, dup item, item 'as item, times 'as Number = 1, begin
>    script, dup item, item "is item", times "is number" = 1, begin
>
> ':' is already heavily used as part of identifiers so unfortunately
> couldn't be used as a separator, unless it was something like "::".
> It might look like "item:Hammer" includes the type, but the "item:" part
> is part of the name so an actual typed declaration would look something
> like
>   variable(item::item:Hammer)  # yuck
>
> ==Syntax for script return types==
>
> The syntax for declaring locals and globals could be the same, e.g.
>   variable([any] tmp, [Slice] sl1, idx)  # idx is a Number, not a Slice
> but declaring the return value of a script is a different matter. E.g.
>   # Don't like this
>   script, [Slice] create shadow, [Slice] from what, length, begin
>   # Putting it afterwards demands consistency
>   script, create shadow [Slice], from what [Slice], length, begin
>   script, create shadow -> Slice, from what -> Slice, length, begin
>   # Unless we allow any order
>   script, create shadow "Slice", "Slice" from what, length, begin
> The return type could be put somewhere else, e.g.
>   script -> Slice, create shadow, from what -> Slice, length, begin
> Or there could be a pseudo-argument named "return" that goes in the
> argument list
>   script, create shadow, return "Slice", from what "Slice", length, begin
>   script, create shadow, [Slice] from what, length, [Slice] return, begin
> Or we could change the syntax for script definitions:
>   script, create shadow ([Slice] from what, length) -> Slice, begin
>
> -> X is especially common syntax for the return type of a
> function. (But note that in type theory and functional languages "X -> Y"
> is notation for the type of a function taking an X and returning a Y)
> _______________________________________________
> Ohrrpgce mailing list
> ohrrpgce at lists.motherhamster.org
> http://lists.motherhamster.org/listinfo.cgi/ohrrpgce-motherhamster.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.motherhamster.org/pipermail/ohrrpgce-motherhamster.org/attachments/20160823/afe196a9/attachment-0001.htm>


More information about the Ohrrpgce mailing list